authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-28 17:15:10+03:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-30 09:57:38+02:00
log6cadac18b8fb1775815fbb3f16f503c5de0e89d0
tree2b02f39c02b1d0bad95ae2f3ae7db47c0862fa19
parent2e7dc5e15192431c64eca458ecfdce3d07b89f69

Sema: improve auto generated union enum name


4 files changed, 67 insertions(+), 32 deletions(-)

src/Module.zig+5
......@@ -503,6 +503,8 @@ pub const Decl = struct {
503503 alive: bool,
504504 /// Whether the Decl is a `usingnamespace` declaration.
505505 is_usingnamespace: bool,
506 /// If true `name` is already fully qualified.
507 name_fully_qualified: bool = false,
506508
507509 /// Represents the position of the code in the output file.
508510 /// This is populated regardless of semantic analysis and code generation.
......@@ -686,6 +688,9 @@ pub const Decl = struct {
686688
687689 pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {
688690 const unqualified_name = mem.sliceTo(decl.name, 0);
691 if (decl.name_fully_qualified) {
692 return writer.writeAll(unqualified_name);
693 }
689694 return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer);
690695 }
691696
src/Sema.zig+43-12
......@@ -14883,7 +14883,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1488314883 union_obj.tag_ty = if (tag_type_val.optionalValue()) |payload_val| blk: {
1488414884 var buffer: Value.ToTypeBuffer = undefined;
1488514885 break :blk try payload_val.toType(&buffer).copy(new_decl_arena_allocator);
14886 } else try sema.generateUnionTagTypeSimple(block, fields_len);
14886 } else try sema.generateUnionTagTypeSimple(block, fields_len, null);
1488714887
1488814888 // Fields
1488914889 if (fields_len > 0) {
......@@ -24237,7 +24237,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
2423724237 if (small.auto_enum_tag) {
2423824238 // The provided type is an integer type and we must construct the enum tag type here.
2423924239 int_tag_ty = provided_ty;
24240 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty);
24240 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty, union_obj);
2424124241 const enum_obj = union_obj.tag_ty.castTag(.enum_numbered).?.data;
2424224242 enum_field_names = &enum_obj.fields;
2424324243 enum_value_map = &enum_obj.values;
......@@ -24253,7 +24253,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
2425324253 // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis
2425424254 // purposes, we still auto-generate an enum tag type the same way. That the union is
2425524255 // untagged is represented by the Type tag (union vs union_tagged).
24256 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, fields_len);
24256 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, fields_len, union_obj);
2425724257 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
2425824258 }
2425924259
......@@ -24422,6 +24422,7 @@ fn generateUnionTagTypeNumbered(
2442224422 block: *Block,
2442324423 fields_len: u32,
2442424424 int_ty: Type,
24425 union_obj: *Module.Union,
2442524426) !Type {
2442624427 const mod = sema.mod;
2442724428
......@@ -24437,13 +24438,24 @@ fn generateUnionTagTypeNumbered(
2443724438 };
2443824439 const enum_ty = Type.initPayload(&enum_ty_payload.base);
2443924440 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
24440 // TODO better type name
24441 const new_decl_index = try mod.createAnonymousDecl(block, .{
24441
24442 const src_decl = mod.declPtr(block.src_decl);
24443 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
24444 errdefer mod.destroyDecl(new_decl_index);
24445 const name = name: {
24446 const fqn = try union_obj.getFullyQualifiedName(mod);
24447 defer sema.gpa.free(fqn);
24448 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
24449 };
24450 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
2444224451 .ty = Type.type,
2444324452 .val = enum_val,
24444 });
24453 }, name);
24454 sema.mod.declPtr(new_decl_index).name_fully_qualified = true;
24455
2444524456 const new_decl = mod.declPtr(new_decl_index);
2444624457 new_decl.owns_tv = true;
24458 new_decl.name_fully_qualified = true;
2444724459 errdefer mod.abortAnonDecl(new_decl_index);
2444824460
2444924461 enum_obj.* = .{
......@@ -24463,7 +24475,7 @@ fn generateUnionTagTypeNumbered(
2446324475 return enum_ty;
2446424476}
2446524477
24466fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Type {
24478fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize, maybe_union_obj: ?*Module.Union) !Type {
2446724479 const mod = sema.mod;
2446824480
2446924481 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
......@@ -24478,11 +24490,30 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Ty
2447824490 };
2447924491 const enum_ty = Type.initPayload(&enum_ty_payload.base);
2448024492 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
24481 // TODO better type name
24482 const new_decl_index = try mod.createAnonymousDecl(block, .{
24483 .ty = Type.type,
24484 .val = enum_val,
24485 });
24493
24494 const new_decl_index = new_decl_index: {
24495 const union_obj = maybe_union_obj orelse {
24496 break :new_decl_index try mod.createAnonymousDecl(block, .{
24497 .ty = Type.type,
24498 .val = enum_val,
24499 });
24500 };
24501 const src_decl = mod.declPtr(block.src_decl);
24502 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
24503 errdefer mod.destroyDecl(new_decl_index);
24504 const name = name: {
24505 const fqn = try union_obj.getFullyQualifiedName(mod);
24506 defer sema.gpa.free(fqn);
24507 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
24508 };
24509 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
24510 .ty = Type.type,
24511 .val = enum_val,
24512 }, name);
24513 sema.mod.declPtr(new_decl_index).name_fully_qualified = true;
24514 break :new_decl_index new_decl_index;
24515 };
24516
2448624517 const new_decl = mod.declPtr(new_decl_index);
2448724518 new_decl.owns_tv = true;
2448824519 errdefer mod.abortAnonDecl(new_decl_index);
test/cases/compile_errors/not_an_enum_type.zig created+19
......@@ -0,0 +1,19 @@
1export fn entry() void {
2 var self: Error = undefined;
3 switch (self) {
4 InvalidToken => |x| return x.token,
5 ExpectedVarDeclOrFn => |x| return x.token,
6 }
7}
8const Error = union(enum) {
9 A: InvalidToken,
10 B: ExpectedVarDeclOrFn,
11};
12const InvalidToken = struct {};
13const ExpectedVarDeclOrFn = struct {};
14
15// error
16// backend=stage2
17// target=native
18//
19// :4:9: error: expected type '@typeInfo(tmp.Error).Union.tag_type.?', found 'type'
test/cases/compile_errors/stage1/test/not_an_enum_type.zig deleted-20
......@@ -1,20 +0,0 @@
1export fn entry() void {
2 var self: Error = undefined;
3 switch (self) {
4 InvalidToken => |x| return x.token,
5 ExpectedVarDeclOrFn => |x| return x.token,
6 }
7}
8const Error = union(enum) {
9 A: InvalidToken,
10 B: ExpectedVarDeclOrFn,
11};
12const InvalidToken = struct {};
13const ExpectedVarDeclOrFn = struct {};
14
15// error
16// backend=stage1
17// target=native
18// is_test=1
19//
20// tmp.zig:4:9: error: expected type '@typeInfo(Error).Union.tag_type.?', found 'type'