aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-06-28 17:15:10 +0300
committerJakub Konka <kubkon@jakubkonka.com>2022-06-30 09:57:38 +0200
commit6cadac18b8fb1775815fbb3f16f503c5de0e89d0 (patch)
tree2b02f39c02b1d0bad95ae2f3ae7db47c0862fa19
parent2e7dc5e15192431c64eca458ecfdce3d07b89f69 (diff)
downloadzig-6cadac18b8fb1775815fbb3f16f503c5de0e89d0.tar.gz
zig-6cadac18b8fb1775815fbb3f16f503c5de0e89d0.zip
Sema: improve auto generated union enum name
-rw-r--r--src/Module.zig5
-rw-r--r--src/Sema.zig55
-rw-r--r--test/cases/compile_errors/not_an_enum_type.zig (renamed from test/cases/compile_errors/stage1/test/not_an_enum_type.zig)5
3 files changed, 50 insertions, 15 deletions
diff --git a/src/Module.zig b/src/Module.zig
index bdf206490d..1f70a44df5 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -503,6 +503,8 @@ pub const Decl = struct {
alive: bool,
/// Whether the Decl is a `usingnamespace` declaration.
is_usingnamespace: bool,
+ /// If true `name` is already fully qualified.
+ name_fully_qualified: bool = false,
/// Represents the position of the code in the output file.
/// This is populated regardless of semantic analysis and code generation.
@@ -686,6 +688,9 @@ pub const Decl = struct {
pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {
const unqualified_name = mem.sliceTo(decl.name, 0);
+ if (decl.name_fully_qualified) {
+ return writer.writeAll(unqualified_name);
+ }
return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer);
}
diff --git a/src/Sema.zig b/src/Sema.zig
index 6f2cad3529..3015ac5d8e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -14883,7 +14883,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
union_obj.tag_ty = if (tag_type_val.optionalValue()) |payload_val| blk: {
var buffer: Value.ToTypeBuffer = undefined;
break :blk try payload_val.toType(&buffer).copy(new_decl_arena_allocator);
- } else try sema.generateUnionTagTypeSimple(block, fields_len);
+ } else try sema.generateUnionTagTypeSimple(block, fields_len, null);
// Fields
if (fields_len > 0) {
@@ -24237,7 +24237,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
if (small.auto_enum_tag) {
// The provided type is an integer type and we must construct the enum tag type here.
int_tag_ty = provided_ty;
- union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty);
+ union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty, union_obj);
const enum_obj = union_obj.tag_ty.castTag(.enum_numbered).?.data;
enum_field_names = &enum_obj.fields;
enum_value_map = &enum_obj.values;
@@ -24253,7 +24253,7 @@ fn semaUnionFields(block: *Block, mod: *Module, union_obj: *Module.Union) Compil
// If auto_enum_tag is false, this is an untagged union. However, for semantic analysis
// purposes, we still auto-generate an enum tag type the same way. That the union is
// untagged is represented by the Type tag (union vs union_tagged).
- union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, fields_len);
+ union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, fields_len, union_obj);
enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
}
@@ -24422,6 +24422,7 @@ fn generateUnionTagTypeNumbered(
block: *Block,
fields_len: u32,
int_ty: Type,
+ union_obj: *Module.Union,
) !Type {
const mod = sema.mod;
@@ -24437,13 +24438,24 @@ fn generateUnionTagTypeNumbered(
};
const enum_ty = Type.initPayload(&enum_ty_payload.base);
const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
- // TODO better type name
- const new_decl_index = try mod.createAnonymousDecl(block, .{
+
+ const src_decl = mod.declPtr(block.src_decl);
+ const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
+ errdefer mod.destroyDecl(new_decl_index);
+ const name = name: {
+ const fqn = try union_obj.getFullyQualifiedName(mod);
+ defer sema.gpa.free(fqn);
+ break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
+ };
+ try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
.ty = Type.type,
.val = enum_val,
- });
+ }, name);
+ sema.mod.declPtr(new_decl_index).name_fully_qualified = true;
+
const new_decl = mod.declPtr(new_decl_index);
new_decl.owns_tv = true;
+ new_decl.name_fully_qualified = true;
errdefer mod.abortAnonDecl(new_decl_index);
enum_obj.* = .{
@@ -24463,7 +24475,7 @@ fn generateUnionTagTypeNumbered(
return enum_ty;
}
-fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Type {
+fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize, maybe_union_obj: ?*Module.Union) !Type {
const mod = sema.mod;
var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
@@ -24478,11 +24490,30 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Ty
};
const enum_ty = Type.initPayload(&enum_ty_payload.base);
const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
- // TODO better type name
- const new_decl_index = try mod.createAnonymousDecl(block, .{
- .ty = Type.type,
- .val = enum_val,
- });
+
+ const new_decl_index = new_decl_index: {
+ const union_obj = maybe_union_obj orelse {
+ break :new_decl_index try mod.createAnonymousDecl(block, .{
+ .ty = Type.type,
+ .val = enum_val,
+ });
+ };
+ const src_decl = mod.declPtr(block.src_decl);
+ const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
+ errdefer mod.destroyDecl(new_decl_index);
+ const name = name: {
+ const fqn = try union_obj.getFullyQualifiedName(mod);
+ defer sema.gpa.free(fqn);
+ break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
+ };
+ try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
+ .ty = Type.type,
+ .val = enum_val,
+ }, name);
+ sema.mod.declPtr(new_decl_index).name_fully_qualified = true;
+ break :new_decl_index new_decl_index;
+ };
+
const new_decl = mod.declPtr(new_decl_index);
new_decl.owns_tv = true;
errdefer mod.abortAnonDecl(new_decl_index);
diff --git a/test/cases/compile_errors/stage1/test/not_an_enum_type.zig b/test/cases/compile_errors/not_an_enum_type.zig
index 99c733b4d0..6868cf7dc0 100644
--- a/test/cases/compile_errors/stage1/test/not_an_enum_type.zig
+++ b/test/cases/compile_errors/not_an_enum_type.zig
@@ -13,8 +13,7 @@ const InvalidToken = struct {};
const ExpectedVarDeclOrFn = struct {};
// error
-// backend=stage1
+// backend=stage2
// target=native
-// is_test=1
//
-// tmp.zig:4:9: error: expected type '@typeInfo(Error).Union.tag_type.?', found 'type'
+// :4:9: error: expected type '@typeInfo(tmp.Error).Union.tag_type.?', found 'type'