@@ -1711,7 +1711,7 @@ fn structInitExpr(
1711
1711
return rvalue(gz, ri, val, node);
1712
1712
},
1713
1713
.none, .ref, .inferred_ptr => {
1714
- return rvalue(gz, ri, .empty_struct , node);
1714
+ return rvalue(gz, ri, .empty_tuple , node);
1715
1715
},
1716
1716
.destructure => |destructure| {
1717
1717
return astgen.failNodeNotes(node, "empty initializer cannot be destructured", .{}, &.{
@@ -1888,6 +1888,8 @@ fn structInitExprAnon(
1888
1888
const tree = astgen.tree;
1889
1889
1890
1890
const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{
1891
+ .abs_node = node,
1892
+ .abs_line = astgen.source_line,
1891
1893
.fields_len = @intCast(struct_init.ast.fields.len),
1892
1894
});
1893
1895
const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).@"struct".fields.len;
@@ -1919,6 +1921,8 @@ fn structInitExprTyped(
1919
1921
const tree = astgen.tree;
1920
1922
1921
1923
const payload_index = try addExtra(astgen, Zir.Inst.StructInit{
1924
+ .abs_node = node,
1925
+ .abs_line = astgen.source_line,
1922
1926
.fields_len = @intCast(struct_init.ast.fields.len),
1923
1927
});
1924
1928
const field_size = @typeInfo(Zir.Inst.StructInit.Item).@"struct".fields.len;
@@ -5007,6 +5011,25 @@ fn structDeclInner(
5007
5011
layout: std.builtin.Type.ContainerLayout,
5008
5012
backing_int_node: Ast.Node.Index,
5009
5013
) InnerError!Zir.Inst.Ref {
5014
+ const astgen = gz.astgen;
5015
+ const gpa = astgen.gpa;
5016
+ const tree = astgen.tree;
5017
+
5018
+ {
5019
+ const is_tuple = for (container_decl.ast.members) |member_node| {
5020
+ const container_field = tree.fullContainerField(member_node) orelse continue;
5021
+ if (container_field.ast.tuple_like) break true;
5022
+ } else false;
5023
+
5024
+ if (is_tuple) {
5025
+ if (node == 0) {
5026
+ return astgen.failTok(0, "file cannot be a tuple", .{});
5027
+ } else {
5028
+ return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);
5029
+ }
5030
+ }
5031
+ }
5032
+
5010
5033
const decl_inst = try gz.reserveInstructionIndex();
5011
5034
5012
5035
if (container_decl.ast.members.len == 0 and backing_int_node == 0) {
@@ -5019,7 +5042,6 @@ fn structDeclInner(
5019
5042
.has_backing_int = false,
5020
5043
.known_non_opv = false,
5021
5044
.known_comptime_only = false,
5022
- .is_tuple = false,
5023
5045
.any_comptime_fields = false,
5024
5046
.any_default_inits = false,
5025
5047
.any_aligned_fields = false,
@@ -5028,10 +5050,6 @@ fn structDeclInner(
5028
5050
return decl_inst.toRef();
5029
5051
}
5030
5052
5031
- const astgen = gz.astgen;
5032
- const gpa = astgen.gpa;
5033
- const tree = astgen.tree;
5034
-
5035
5053
var namespace: Scope.Namespace = .{
5036
5054
.parent = scope,
5037
5055
.node = node,
@@ -5106,46 +5124,6 @@ fn structDeclInner(
5106
5124
// No defer needed here because it is handled by `wip_members.deinit()` above.
5107
5125
const bodies_start = astgen.scratch.items.len;
5108
5126
5109
- const node_tags = tree.nodes.items(.tag);
5110
- const is_tuple = for (container_decl.ast.members) |member_node| {
5111
- const container_field = tree.fullContainerField(member_node) orelse continue;
5112
- if (container_field.ast.tuple_like) break true;
5113
- } else false;
5114
-
5115
- if (is_tuple) switch (layout) {
5116
- .auto => {},
5117
- .@"extern" => return astgen.failNode(node, "extern tuples are not supported", .{}),
5118
- .@"packed" => return astgen.failNode(node, "packed tuples are not supported", .{}),
5119
- };
5120
-
5121
- if (is_tuple) for (container_decl.ast.members) |member_node| {
5122
- switch (node_tags[member_node]) {
5123
- .container_field_init,
5124
- .container_field_align,
5125
- .container_field,
5126
- .@"comptime",
5127
- .test_decl,
5128
- => continue,
5129
- else => {
5130
- const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) {
5131
- .container_field_init,
5132
- .container_field_align,
5133
- .container_field,
5134
- => break maybe_tuple,
5135
- else => {},
5136
- } else unreachable;
5137
- return astgen.failNodeNotes(
5138
- member_node,
5139
- "tuple declarations cannot contain declarations",
5140
- .{},
5141
- &[_]u32{
5142
- try astgen.errNoteNode(tuple_member, "tuple field here", .{}),
5143
- },
5144
- );
5145
- },
5146
- }
5147
- };
5148
-
5149
5127
const old_hasher = astgen.src_hasher;
5150
5128
defer astgen.src_hasher = old_hasher;
5151
5129
astgen.src_hasher = std.zig.SrcHasher.init(.{});
@@ -5167,16 +5145,10 @@ fn structDeclInner(
5167
5145
5168
5146
astgen.src_hasher.update(tree.getNodeSource(member_node));
5169
5147
5170
- if (!is_tuple) {
5171
- const field_name = try astgen.identAsString(member.ast.main_token);
5172
-
5173
- member.convertToNonTupleLike(astgen.tree.nodes);
5174
- assert(!member.ast.tuple_like);
5175
-
5176
- wip_members.appendToField(@intFromEnum(field_name));
5177
- } else if (!member.ast.tuple_like) {
5178
- return astgen.failTok(member.ast.main_token, "tuple field has a name", .{});
5179
- }
5148
+ const field_name = try astgen.identAsString(member.ast.main_token);
5149
+ member.convertToNonTupleLike(astgen.tree.nodes);
5150
+ assert(!member.ast.tuple_like);
5151
+ wip_members.appendToField(@intFromEnum(field_name));
5180
5152
5181
5153
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
5182
5154
wip_members.appendToField(@intFromEnum(doc_comment_index));
@@ -5270,7 +5242,6 @@ fn structDeclInner(
5270
5242
.has_backing_int = backing_int_ref != .none,
5271
5243
.known_non_opv = known_non_opv,
5272
5244
.known_comptime_only = known_comptime_only,
5273
- .is_tuple = is_tuple,
5274
5245
.any_comptime_fields = any_comptime_fields,
5275
5246
.any_default_inits = any_default_inits,
5276
5247
.any_aligned_fields = any_aligned_fields,
@@ -5300,6 +5271,106 @@ fn structDeclInner(
5300
5271
return decl_inst.toRef();
5301
5272
}
5302
5273
5274
+ fn tupleDecl(
5275
+ gz: *GenZir,
5276
+ scope: *Scope,
5277
+ node: Ast.Node.Index,
5278
+ container_decl: Ast.full.ContainerDecl,
5279
+ layout: std.builtin.Type.ContainerLayout,
5280
+ backing_int_node: Ast.Node.Index,
5281
+ ) InnerError!Zir.Inst.Ref {
5282
+ const astgen = gz.astgen;
5283
+ const gpa = astgen.gpa;
5284
+ const tree = astgen.tree;
5285
+
5286
+ const node_tags = tree.nodes.items(.tag);
5287
+
5288
+ switch (layout) {
5289
+ .auto => {},
5290
+ .@"extern" => return astgen.failNode(node, "extern tuples are not supported", .{}),
5291
+ .@"packed" => return astgen.failNode(node, "packed tuples are not supported", .{}),
5292
+ }
5293
+
5294
+ if (backing_int_node != 0) {
5295
+ return astgen.failNode(backing_int_node, "tuple does not support backing integer type", .{});
5296
+ }
5297
+
5298
+ // We will use the scratch buffer, starting here, for the field data:
5299
+ // 1. fields: { // for every `fields_len` (stored in `extended.small`)
5300
+ // type: Inst.Ref,
5301
+ // init: Inst.Ref, // `.none` for non-`comptime` fields
5302
+ // }
5303
+ const fields_start = astgen.scratch.items.len;
5304
+ defer astgen.scratch.items.len = fields_start;
5305
+
5306
+ try astgen.scratch.ensureUnusedCapacity(gpa, container_decl.ast.members.len * 2);
5307
+
5308
+ for (container_decl.ast.members) |member_node| {
5309
+ const field = tree.fullContainerField(member_node) orelse {
5310
+ const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) {
5311
+ .container_field_init,
5312
+ .container_field_align,
5313
+ .container_field,
5314
+ => break maybe_tuple,
5315
+ else => {},
5316
+ } else unreachable;
5317
+ return astgen.failNodeNotes(
5318
+ member_node,
5319
+ "tuple declarations cannot contain declarations",
5320
+ .{},
5321
+ &.{try astgen.errNoteNode(tuple_member, "tuple field here", .{})},
5322
+ );
5323
+ };
5324
+
5325
+ if (!field.ast.tuple_like) {
5326
+ return astgen.failTok(field.ast.main_token, "tuple field has a name", .{});
5327
+ }
5328
+
5329
+ if (field.ast.align_expr != 0) {
5330
+ return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});
5331
+ }
5332
+
5333
+ if (field.ast.value_expr != 0 and field.comptime_token == null) {
5334
+ return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{});
5335
+ }
5336
+
5337
+ if (field.ast.value_expr == 0 and field.comptime_token != null) {
5338
+ return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{});
5339
+ }
5340
+
5341
+ const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr);
5342
+ astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));
5343
+
5344
+ if (field.ast.value_expr != 0) {
5345
+ const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr);
5346
+ astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
5347
+ } else {
5348
+ astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
5349
+ }
5350
+ }
5351
+
5352
+ const fields_len = std.math.cast(u16, container_decl.ast.members.len) orelse {
5353
+ return astgen.failNode(node, "this compiler implementation only supports 65535 tuple fields", .{});
5354
+ };
5355
+
5356
+ const extra_trail = astgen.scratch.items[fields_start..];
5357
+ assert(extra_trail.len == fields_len * 2);
5358
+ try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.TupleDecl).@"struct".fields.len + extra_trail.len);
5359
+ const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.TupleDecl{
5360
+ .src_node = gz.nodeIndexToRelative(node),
5361
+ });
5362
+ astgen.extra.appendSliceAssumeCapacity(extra_trail);
5363
+
5364
+ return gz.add(.{
5365
+ .tag = .extended,
5366
+ .data = .{ .extended = .{
5367
+ .opcode = .tuple_decl,
5368
+ .small = fields_len,
5369
+ .operand = payload_index,
5370
+ } },
5371
+ });
5372
+ }
5373
+
5303
5374
fn unionDeclInner(
5304
5375
gz: *GenZir,
5305
5376
scope: *Scope,
@@ -11172,7 +11243,7 @@ fn rvalueInner(
11172
11243
as_ty | @intFromEnum(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),
11173
11244
as_ty | @intFromEnum(Zir.Inst.Ref.anyerror_void_error_union_type),
11174
11245
as_ty | @intFromEnum(Zir.Inst.Ref.generic_poison_type),
11175
- as_ty | @intFromEnum(Zir.Inst.Ref.empty_struct_type ),
11246
+ as_ty | @intFromEnum(Zir.Inst.Ref.empty_tuple_type ),
11176
11247
as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero),
11177
11248
as_comptime_int | @intFromEnum(Zir.Inst.Ref.one),
11178
11249
as_comptime_int | @intFromEnum(Zir.Inst.Ref.negative_one),
@@ -13173,7 +13244,6 @@ const GenZir = struct {
13173
13244
layout: std.builtin.Type.ContainerLayout,
13174
13245
known_non_opv: bool,
13175
13246
known_comptime_only: bool,
13176
- is_tuple: bool,
13177
13247
any_comptime_fields: bool,
13178
13248
any_default_inits: bool,
13179
13249
any_aligned_fields: bool,
@@ -13217,7 +13287,6 @@ const GenZir = struct {
13217
13287
.has_backing_int = args.has_backing_int,
13218
13288
.known_non_opv = args.known_non_opv,
13219
13289
.known_comptime_only = args.known_comptime_only,
13220
- .is_tuple = args.is_tuple,
13221
13290
.name_strategy = gz.anon_name_strategy,
13222
13291
.layout = args.layout,
13223
13292
.any_comptime_fields = args.any_comptime_fields,
0 commit comments