Commit 80575face7
Changed files (4)
src/AstGen.zig
@@ -4386,6 +4386,7 @@ fn structDeclInner(
.backing_int_body_len = 0,
.known_non_opv = false,
.known_comptime_only = false,
+ .is_tuple = false,
});
return indexToRef(decl_inst);
}
@@ -4467,22 +4468,59 @@ fn structDeclInner(
// No defer needed here because it is handled by `wip_members.deinit()` above.
const bodies_start = astgen.scratch.items.len;
+ var is_tuple = false;
+ const node_tags = tree.nodes.items(.tag);
+ for (container_decl.ast.members) |member_node| {
+ switch (node_tags[member_node]) {
+ .container_field_init => is_tuple = tree.containerFieldInit(member_node).ast.tuple_like,
+ .container_field_align => is_tuple = tree.containerFieldAlign(member_node).ast.tuple_like,
+ .container_field => is_tuple = tree.containerField(member_node).ast.tuple_like,
+ else => continue,
+ }
+ if (is_tuple) break;
+ }
+ if (is_tuple) for (container_decl.ast.members) |member_node| {
+ switch (node_tags[member_node]) {
+ .container_field_init,
+ .container_field_align,
+ .container_field,
+ .@"comptime",
+ => continue,
+ else => {
+ return astgen.failNode(member_node, "tuple declarations cannot contain declarations", .{});
+ },
+ }
+ };
+
var known_non_opv = false;
var known_comptime_only = false;
for (container_decl.ast.members) |member_node| {
- const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
+ var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
.decl => continue,
.field => |field| field,
};
+ if (member.ast.tuple_like and !is_tuple and member.ast.type_expr != 0 and
+ astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
+ {
+ const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
+ member.ast.tuple_like = false;
+ member.ast.main_token = ident;
+ member.ast.type_expr = 0;
+ } else if (is_tuple and !member.ast.tuple_like) {
+ return astgen.failTok(member.ast.main_token, "tuple field has a name", .{});
+ }
- const field_name = try astgen.identAsString(member.ast.name_token);
- wip_members.appendToField(field_name);
+ if (!is_tuple) {
+ if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "struct field missing name", .{});
+ const field_name = try astgen.identAsString(member.ast.main_token);
+ wip_members.appendToField(field_name);
+ }
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
wip_members.appendToField(doc_comment_index);
if (member.ast.type_expr == 0) {
- return astgen.failTok(member.ast.name_token, "struct field missing type", .{});
+ return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
}
const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
@@ -4562,6 +4600,7 @@ fn structDeclInner(
.backing_int_body_len = @intCast(u32, backing_int_body_len),
.known_non_opv = known_non_opv,
.known_comptime_only = known_comptime_only,
+ .is_tuple = is_tuple,
});
wip_members.finishBits(bits_per_field);
@@ -4640,15 +4679,25 @@ fn unionDeclInner(
defer wip_members.deinit();
for (members) |member_node| {
- const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
+ var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
.decl => continue,
.field => |field| field,
};
+ if (member.ast.tuple_like and member.ast.type_expr != 0 and
+ astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
+ {
+ const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
+ member.ast.tuple_like = false;
+ member.ast.main_token = ident;
+ member.ast.type_expr = 0;
+ } else if (member.ast.tuple_like) {
+ return astgen.failTok(member.ast.main_token, "union field missing name", .{});
+ }
if (member.comptime_token) |comptime_token| {
return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
}
- const field_name = try astgen.identAsString(member.ast.name_token);
+ const field_name = try astgen.identAsString(member.ast.main_token);
wip_members.appendToField(field_name);
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
@@ -4787,7 +4836,7 @@ fn containerDecl(
var nonexhaustive_node: Ast.Node.Index = 0;
var nonfinal_nonexhaustive = false;
for (container_decl.ast.members) |member_node| {
- const member = switch (node_tags[member_node]) {
+ var member = switch (node_tags[member_node]) {
.container_field_init => tree.containerFieldInit(member_node),
.container_field_align => tree.containerFieldAlign(member_node),
.container_field => tree.containerField(member_node),
@@ -4796,6 +4845,16 @@ fn containerDecl(
continue;
},
};
+ if (member.ast.tuple_like and member.ast.type_expr != 0 and
+ astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
+ {
+ const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
+ member.ast.tuple_like = false;
+ member.ast.main_token = ident;
+ member.ast.type_expr = 0;
+ } else if (member.ast.tuple_like) {
+ return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
+ }
if (member.comptime_token) |comptime_token| {
return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
}
@@ -4816,7 +4875,7 @@ fn containerDecl(
// Alignment expressions in enums are caught by the parser.
assert(member.ast.align_expr == 0);
- const name_token = member.ast.name_token;
+ const name_token = member.ast.main_token;
if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
if (nonexhaustive_node != 0) {
return astgen.failNodeNotes(
@@ -4915,15 +4974,23 @@ fn containerDecl(
for (container_decl.ast.members) |member_node| {
if (member_node == counts.nonexhaustive_node)
continue;
- const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
+ var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
.decl => continue,
.field => |field| field,
};
+ if (member.ast.tuple_like and member.ast.type_expr != 0 and
+ astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
+ {
+ const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
+ member.ast.tuple_like = false;
+ member.ast.main_token = ident;
+ member.ast.type_expr = 0;
+ }
assert(member.comptime_token == null);
assert(member.ast.type_expr == 0);
assert(member.ast.align_expr == 0);
- const field_name = try astgen.identAsString(member.ast.name_token);
+ const field_name = try astgen.identAsString(member.ast.main_token);
wip_members.appendToField(field_name);
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
@@ -11786,6 +11853,7 @@ const GenZir = struct {
layout: std.builtin.Type.ContainerLayout,
known_non_opv: bool,
known_comptime_only: bool,
+ is_tuple: bool,
}) !void {
const astgen = gz.astgen;
const gpa = astgen.gpa;
@@ -11820,6 +11888,7 @@ const GenZir = struct {
.has_backing_int = args.backing_int_ref != .none,
.known_non_opv = args.known_non_opv,
.known_comptime_only = args.known_comptime_only,
+ .is_tuple = args.is_tuple,
.name_strategy = gz.anon_name_strategy,
.layout = args.layout,
}),
src/Module.zig
@@ -6138,7 +6138,7 @@ fn queryFieldSrc(
.name => .{
.file_scope = file_scope,
.parent_decl_node = 0,
- .lazy = .{ .token_abs = field.ast.name_token },
+ .lazy = .{ .token_abs = field.ast.main_token },
},
.type => .{
.file_scope = file_scope,
src/print_zir.zig
@@ -1262,6 +1262,7 @@ const Writer = struct {
try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
+ try self.writeFlag(stream, "tuple, ", small.is_tuple);
try stream.print("{s}, ", .{@tagName(small.name_strategy)});
@@ -1335,8 +1336,11 @@ const Writer = struct {
const has_type_body = @truncate(u1, cur_bit_bag) != 0;
cur_bit_bag >>= 1;
- const field_name = self.code.extra[extra_index];
- extra_index += 1;
+ var field_name: u32 = 0;
+ if (!small.is_tuple) {
+ field_name = self.code.extra[extra_index];
+ extra_index += 1;
+ }
const doc_comment_index = self.code.extra[extra_index];
extra_index += 1;
@@ -1370,13 +1374,16 @@ const Writer = struct {
try stream.writeAll("{\n");
self.indent += 2;
- for (fields) |field| {
- const field_name = self.code.nullTerminatedString(field.name);
-
+ for (fields) |field, i| {
try self.writeDocComment(stream, field.doc_comment_index);
try stream.writeByteNTimes(' ', self.indent);
try self.writeFlag(stream, "comptime ", field.is_comptime);
- try stream.print("{}: ", .{std.zig.fmtId(field_name)});
+ if (field.name != 0) {
+ const field_name = self.code.nullTerminatedString(field.name);
+ try stream.print("{}: ", .{std.zig.fmtId(field_name)});
+ } else {
+ try stream.print("@\"{d}\": ", .{i});
+ }
if (field.field_type != .none) {
try self.writeInstRef(stream, field.field_type);
}
src/Zir.zig
@@ -3166,7 +3166,7 @@ pub const Inst = struct {
/// 0b0X00: whether corresponding field is comptime
/// 0bX000: whether corresponding field has a type expression
/// 9. fields: { // for every fields_len
- /// field_name: u32,
+ /// field_name: u32, // if !is_tuple
/// doc_comment: u32, // 0 if no doc comment
/// field_type: Ref, // if corresponding bit is not set. none means anytype.
/// field_type_body_len: u32, // if corresponding bit is set
@@ -3186,9 +3186,10 @@ pub const Inst = struct {
has_backing_int: bool,
known_non_opv: bool,
known_comptime_only: bool,
+ is_tuple: bool,
name_strategy: NameStrategy,
layout: std.builtin.Type.ContainerLayout,
- _: u6 = undefined,
+ _: u5 = undefined,
};
};