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 {...@@ -503,6 +503,8 @@ pub const Decl = struct {
503 alive: bool,503 alive: bool,
504 /// Whether the Decl is a `usingnamespace` declaration.504 /// Whether the Decl is a `usingnamespace` declaration.
505 is_usingnamespace: bool,505 is_usingnamespace: bool,
506 /// If true `name` is already fully qualified.
507 name_fully_qualified: bool = false,
506508
507 /// Represents the position of the code in the output file.509 /// Represents the position of the code in the output file.
508 /// This is populated regardless of semantic analysis and code generation.510 /// This is populated regardless of semantic analysis and code generation.
...@@ -686,6 +688,9 @@ pub const Decl = struct {...@@ -686,6 +688,9 @@ pub const Decl = struct {
686688
687 pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {689 pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {
688 const unqualified_name = mem.sliceTo(decl.name, 0);690 const unqualified_name = mem.sliceTo(decl.name, 0);
691 if (decl.name_fully_qualified) {
692 return writer.writeAll(unqualified_name);
693 }
689 return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer);694 return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer);
690 }695 }
691696
src/Sema.zig+43-12
...@@ -14883,7 +14883,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -14883,7 +14883,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
14883 union_obj.tag_ty = if (tag_type_val.optionalValue()) |payload_val| blk: {14883 union_obj.tag_ty = if (tag_type_val.optionalValue()) |payload_val| blk: {
14884 var buffer: Value.ToTypeBuffer = undefined;14884 var buffer: Value.ToTypeBuffer = undefined;
14885 break :blk try payload_val.toType(&buffer).copy(new_decl_arena_allocator);14885 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
14888 // Fields14888 // Fields
14889 if (fields_len > 0) {14889 if (fields_len > 0) {
...@@ -24237,7 +24237,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil...@@ -24237,7 +24237,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
24237 if (small.auto_enum_tag) {24237 if (small.auto_enum_tag) {
24238 // The provided type is an integer type and we must construct the enum tag type here.24238 // The provided type is an integer type and we must construct the enum tag type here.
24239 int_tag_ty = provided_ty;24239 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);
24241 const enum_obj = union_obj.tag_ty.castTag(.enum_numbered).?.data;24241 const enum_obj = union_obj.tag_ty.castTag(.enum_numbered).?.data;
24242 enum_field_names = &enum_obj.fields;24242 enum_field_names = &enum_obj.fields;
24243 enum_value_map = &enum_obj.values;24243 enum_value_map = &enum_obj.values;
...@@ -24253,7 +24253,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil...@@ -24253,7 +24253,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
24253 // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis24253 // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis
24254 // purposes, we still auto-generate an enum tag type the same way. That the union is24254 // purposes, we still auto-generate an enum tag type the same way. That the union is
24255 // untagged is represented by the Type tag (union vs union_tagged).24255 // 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);
24257 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;24257 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
24258 }24258 }
2425924259
...@@ -24422,6 +24422,7 @@ fn generateUnionTagTypeNumbered(...@@ -24422,6 +24422,7 @@ fn generateUnionTagTypeNumbered(
24422 block: *Block,24422 block: *Block,
24423 fields_len: u32,24423 fields_len: u32,
24424 int_ty: Type,24424 int_ty: Type,
24425 union_obj: *Module.Union,
24425) !Type {24426) !Type {
24426 const mod = sema.mod;24427 const mod = sema.mod;
2442724428
...@@ -24437,13 +24438,24 @@ fn generateUnionTagTypeNumbered(...@@ -24437,13 +24438,24 @@ fn generateUnionTagTypeNumbered(
24437 };24438 };
24438 const enum_ty = Type.initPayload(&enum_ty_payload.base);24439 const enum_ty = Type.initPayload(&enum_ty_payload.base);
24439 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);24440 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
24440 // TODO better type name24441
24441 const new_decl_index = try mod.createAnonymousDecl(block, .{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, .{
24442 .ty = Type.type,24451 .ty = Type.type,
24443 .val = enum_val,24452 .val = enum_val,
24444 });24453 }, name);
24454 sema.mod.declPtr(new_decl_index).name_fully_qualified = true;
24455
24445 const new_decl = mod.declPtr(new_decl_index);24456 const new_decl = mod.declPtr(new_decl_index);
24446 new_decl.owns_tv = true;24457 new_decl.owns_tv = true;
24458 new_decl.name_fully_qualified = true;
24447 errdefer mod.abortAnonDecl(new_decl_index);24459 errdefer mod.abortAnonDecl(new_decl_index);
2444824460
24449 enum_obj.* = .{24461 enum_obj.* = .{
...@@ -24463,7 +24475,7 @@ fn generateUnionTagTypeNumbered(...@@ -24463,7 +24475,7 @@ fn generateUnionTagTypeNumbered(
24463 return enum_ty;24475 return enum_ty;
24464}24476}
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 {
24467 const mod = sema.mod;24479 const mod = sema.mod;
2446824480
24469 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);24481 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
...@@ -24478,11 +24490,30 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Ty...@@ -24478,11 +24490,30 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Ty
24478 };24490 };
24479 const enum_ty = Type.initPayload(&enum_ty_payload.base);24491 const enum_ty = Type.initPayload(&enum_ty_payload.base);
24480 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);24492 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
24481 // TODO better type name24493
24482 const new_decl_index = try mod.createAnonymousDecl(block, .{24494 const new_decl_index = new_decl_index: {
24483 .ty = Type.type,24495 const union_obj = maybe_union_obj orelse {
24484 .val = enum_val,24496 break :new_decl_index try mod.createAnonymousDecl(block, .{
24485 });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
24486 const new_decl = mod.declPtr(new_decl_index);24517 const new_decl = mod.declPtr(new_decl_index);
24487 new_decl.owns_tv = true;24518 new_decl.owns_tv = true;
24488 errdefer mod.abortAnonDecl(new_decl_index);24519 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'