commit f42725c39bbbe5db13c1a1706db3f31aa0549307 (tree)
parent d1fd864da7859989828feb8be806634606cc761c
Author: Andrew Kelley <andrew@ziglang.org>
Date: Sun, 10 Oct 2021 15:22:17 -0400
Merge pull request #9925 from mattbork/uniondecl-fixes
stage2: astgen unionDecl fixes
Diffstat:
4 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/src/AstGen.zig b/src/AstGen.zig
@@ -4134,7 +4134,7 @@ fn unionDeclInner(
if (member.comptime_token) |comptime_token| {
return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
}
- try fields_data.ensureUnusedCapacity(gpa, if (node_tags[member.ast.type_expr] != .@"anytype") 4 else 3);
+ try fields_data.ensureUnusedCapacity(gpa, 4);
const field_name = try astgen.identAsString(member.ast.name_token);
fields_data.appendAssumeCapacity(field_name);
@@ -4149,9 +4149,14 @@ fn unionDeclInner(
(@as(u32, @boolToInt(have_value)) << 30) |
(@as(u32, @boolToInt(unused)) << 31);
- if (have_type and node_tags[member.ast.type_expr] != .@"anytype") {
- const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
+ if (have_type) {
+ const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
+ .none
+ else
+ try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
fields_data.appendAssumeCapacity(@enumToInt(field_type));
+ } else if (arg_inst == .none and !have_auto_enum) {
+ return astgen.failNode(member_node, "union field missing type", .{});
}
if (have_align) {
const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);
@@ -4172,6 +4177,20 @@ fn unionDeclInner(
},
);
}
+ if (!have_auto_enum) {
+ return astgen.failNodeNotes(
+ node,
+ "explicitly valued tagged union requires inferred enum tag type",
+ .{},
+ &[_]u32{
+ try astgen.errNoteNode(
+ member.ast.value_expr,
+ "tag value specified here",
+ .{},
+ ),
+ },
+ );
+ }
const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
fields_data.appendAssumeCapacity(@enumToInt(tag_value));
}
diff --git a/src/Sema.zig b/src/Sema.zig
@@ -12629,8 +12629,10 @@ fn semaUnionFields(
set.putAssumeCapacity(field_name, {});
}
- const field_ty: Type = if (field_type_ref == .none)
+ const field_ty: Type = if (!has_type)
Type.initTag(.void)
+ else if (field_type_ref == .none)
+ Type.initTag(.noreturn)
else
// TODO: if we need to report an error here, use a source location
// that points to this type expression rather than the union.
diff --git a/src/Zir.zig b/src/Zir.zig
@@ -2686,6 +2686,7 @@ pub const Inst = struct {
/// 9. fields: { // for every fields_len
/// field_name: u32, // null terminated string index
/// field_type: Ref, // if corresponding bit is set
+ /// - if none, means `anytype`.
/// align: Ref, // if corresponding bit is set
/// tag_value: Ref, // if corresponding bit is set
/// }
diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig
@@ -571,6 +571,40 @@ pub fn addCases(ctx: *TestContext) !void {
}
{
+ var case = ctx.exeFromCompiledC("unions", .{});
+
+ case.addError(
+ \\const U = union {
+ \\ a: u32,
+ \\ b
+ \\};
+ , &.{
+ ":3:5: error: union field missing type",
+ });
+
+ case.addError(
+ \\const E = enum { a, b };
+ \\const U = union(E) {
+ \\ a: u32 = 1,
+ \\ b: f32 = 2,
+ \\};
+ , &.{
+ ":2:11: error: explicitly valued tagged union requires inferred enum tag type",
+ ":3:14: note: tag value specified here",
+ });
+
+ case.addError(
+ \\const U = union(enum) {
+ \\ a: u32 = 1,
+ \\ b: f32 = 2,
+ \\};
+ , &.{
+ ":1:11: error: explicitly valued tagged union missing integer tag type",
+ ":2:14: note: tag value specified here",
+ });
+ }
+
+ {
var case = ctx.exeFromCompiledC("enums", .{});
case.addError(