authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-10-26 23:13:58+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-10-31 20:42:53+00:00
logd11bbde5f9c64ef58405604601d55f88bb5d5f3a
tree4e05b679cd791e90db68f3f2198294667a6fc57c
parenta916bc7fdd3975a9e2ef13c44f814c71ce017193
signaturelock-open Commit is signed but in an unrecognized format.

compiler: remove anonymous struct types, unify all tuples

This commit reworks how anonymous struct literals and tuples work. Previously, an untyped anonymous struct literal (e.g. `const x = .{ .a = 123 }`) was given an "anonymous struct type", which is a special kind of struct which coerces using structural equivalence. This mechanism was a holdover from before we used RLS / result types as the primary mechanism of type inference. This commit changes the language so that the type assigned here is a "normal" struct type. It uses a form of equivalence based on the AST node and the type's structure, much like a reified (`@Type`) type. Additionally, tuples have been simplified. The distinction between "simple" and "complex" tuple types is eliminated. All tuples, even those explicitly declared using `struct { ... }` syntax, use structural equivalence, and do not undergo staged type resolution. Tuples are very restricted: they cannot have non-`auto` layouts, cannot have aligned fields, and cannot have default values with the exception of `comptime` fields. Tuples currently do not have optimized layout, but this can be changed in the future. This change simplifies the language, and fixes some problematic coercions through pointers which led to unintuitive behavior. Resolves: #16865

62 files changed, 1066 insertions(+), 1313 deletions(-)

lib/compiler/aro/aro/Builtins.zig+1-1
...@@ -157,7 +157,7 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *c...@@ -157,7 +157,7 @@ fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *c
157 .len = element_count,157 .len = element_count,
158 .elem = child_ty,158 .elem = child_ty,
159 };159 };
160 const vector_ty = .{ .specifier = .vector, .data = .{ .array = arr_ty } };160 const vector_ty: Type = .{ .specifier = .vector, .data = .{ .array = arr_ty } };
161 builder.specifier = Type.Builder.fromType(vector_ty);161 builder.specifier = Type.Builder.fromType(vector_ty);
162 },162 },
163 .q => {163 .q => {
lib/compiler/aro/aro/Parser.zig+1-1
...@@ -8095,7 +8095,7 @@ fn primaryExpr(p: *Parser) Error!Result {...@@ -8095,7 +8095,7 @@ fn primaryExpr(p: *Parser) Error!Result {
80958095
8096fn makePredefinedIdentifier(p: *Parser, strings_top: usize) !Result {8096fn makePredefinedIdentifier(p: *Parser, strings_top: usize) !Result {
8097 const end: u32 = @intCast(p.strings.items.len);8097 const end: u32 = @intCast(p.strings.items.len);
8098 const elem_ty = .{ .specifier = .char, .qual = .{ .@"const" = true } };8098 const elem_ty: Type = .{ .specifier = .char, .qual = .{ .@"const" = true } };
8099 const arr_ty = try p.arena.create(Type.Array);8099 const arr_ty = try p.arena.create(Type.Array);
8100 arr_ty.* = .{ .elem = elem_ty, .len = end - strings_top };8100 arr_ty.* = .{ .elem = elem_ty, .len = end - strings_top };
8101 const ty: Type = .{ .specifier = .array, .data = .{ .array = arr_ty } };8101 const ty: Type = .{ .specifier = .array, .data = .{ .array = arr_ty } };
lib/compiler/aro/aro/text_literal.zig+1-1
...@@ -188,7 +188,7 @@ pub const Parser = struct {...@@ -188,7 +188,7 @@ pub const Parser = struct {
188 pub fn err(self: *Parser, tag: Diagnostics.Tag, extra: Diagnostics.Message.Extra) void {188 pub fn err(self: *Parser, tag: Diagnostics.Tag, extra: Diagnostics.Message.Extra) void {
189 if (self.errored) return;189 if (self.errored) return;
190 self.errored = true;190 self.errored = true;
191 const diagnostic = .{ .tag = tag, .extra = extra };191 const diagnostic: CharDiagnostic = .{ .tag = tag, .extra = extra };
192 if (self.errors_len == self.errors_buffer.len) {192 if (self.errors_len == self.errors_buffer.len) {
193 self.errors_buffer[self.errors_buffer.len - 1] = diagnostic;193 self.errors_buffer[self.errors_buffer.len - 1] = diagnostic;
194 } else {194 } else {
lib/compiler/aro_translate_c.zig+1-1
...@@ -749,7 +749,7 @@ fn transType(c: *Context, scope: *Scope, raw_ty: Type, qual_handling: Type.QualH...@@ -749,7 +749,7 @@ fn transType(c: *Context, scope: *Scope, raw_ty: Type, qual_handling: Type.QualH
749 const is_const = is_fn_proto or child_type.isConst();749 const is_const = is_fn_proto or child_type.isConst();
750 const is_volatile = child_type.qual.@"volatile";750 const is_volatile = child_type.qual.@"volatile";
751 const elem_type = try transType(c, scope, child_type, qual_handling, source_loc);751 const elem_type = try transType(c, scope, child_type, qual_handling, source_loc);
752 const ptr_info = .{752 const ptr_info: @FieldType(ast.Payload.Pointer, "data") = .{
753 .is_const = is_const,753 .is_const = is_const,
754 .is_volatile = is_volatile,754 .is_volatile = is_volatile,
755 .elem_type = elem_type,755 .elem_type = elem_type,
lib/compiler/test_runner.zig+1-1
...@@ -6,7 +6,7 @@ const io = std.io;...@@ -6,7 +6,7 @@ const io = std.io;
6const testing = std.testing;6const testing = std.testing;
7const assert = std.debug.assert;7const assert = std.debug.assert;
88
9pub const std_options = .{9pub const std_options: std.Options = .{
10 .logFn = log,10 .logFn = log,
11};11};
1212
lib/std/SemanticVersion.zig+1-1
...@@ -299,7 +299,7 @@ test "precedence" {...@@ -299,7 +299,7 @@ test "precedence" {
299299
300test "zig_version" {300test "zig_version" {
301 // An approximate Zig build that predates this test.301 // An approximate Zig build that predates this test.
302 const older_version = .{ .major = 0, .minor = 8, .patch = 0, .pre = "dev.874" };302 const older_version: Version = .{ .major = 0, .minor = 8, .patch = 0, .pre = "dev.874" };
303303
304 // Simulated compatibility check using Zig version.304 // Simulated compatibility check using Zig version.
305 const compatible = comptime @import("builtin").zig_version.order(older_version) == .gt;305 const compatible = comptime @import("builtin").zig_version.order(older_version) == .gt;
lib/std/Target.zig+1-1
...@@ -509,7 +509,7 @@ pub const Os = struct {...@@ -509,7 +509,7 @@ pub const Os = struct {
509 .max = .{ .major = 6, .minor = 10, .patch = 3 },509 .max = .{ .major = 6, .minor = 10, .patch = 3 },
510 },510 },
511 .glibc = blk: {511 .glibc = blk: {
512 const default_min = .{ .major = 2, .minor = 28, .patch = 0 };512 const default_min: std.SemanticVersion = .{ .major = 2, .minor = 28, .patch = 0 };
513513
514 for (std.zig.target.available_libcs) |libc| {514 for (std.zig.target.available_libcs) |libc| {
515 // We don't know the ABI here. We can get away with not checking it515 // We don't know the ABI here. We can get away with not checking it
lib/std/array_list.zig+1-1
...@@ -100,7 +100,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -100,7 +100,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
100 /// of this ArrayList. Empties this ArrayList.100 /// of this ArrayList. Empties this ArrayList.
101 pub fn moveToUnmanaged(self: *Self) ArrayListAlignedUnmanaged(T, alignment) {101 pub fn moveToUnmanaged(self: *Self) ArrayListAlignedUnmanaged(T, alignment) {
102 const allocator = self.allocator;102 const allocator = self.allocator;
103 const result = .{ .items = self.items, .capacity = self.capacity };103 const result: ArrayListAlignedUnmanaged(T, alignment) = .{ .items = self.items, .capacity = self.capacity };
104 self.* = init(allocator);104 self.* = init(allocator);
105 return result;105 return result;
106 }106 }
lib/std/crypto/phc_encoding.zig+1-2
...@@ -258,8 +258,7 @@ fn kvSplit(str: []const u8) !struct { key: []const u8, value: []const u8 } {...@@ -258,8 +258,7 @@ fn kvSplit(str: []const u8) !struct { key: []const u8, value: []const u8 } {
258 var it = mem.splitScalar(u8, str, kv_delimiter_scalar);258 var it = mem.splitScalar(u8, str, kv_delimiter_scalar);
259 const key = it.first();259 const key = it.first();
260 const value = it.next() orelse return Error.InvalidEncoding;260 const value = it.next() orelse return Error.InvalidEncoding;
261 const ret = .{ .key = key, .value = value };261 return .{ .key = key, .value = value };
262 return ret;
263}262}
264263
265test "phc format - encoding/decoding" {264test "phc format - encoding/decoding" {
lib/std/meta.zig+1-1
...@@ -1018,7 +1018,7 @@ fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type {...@@ -1018,7 +1018,7 @@ fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type {
1018 .type = T,1018 .type = T,
1019 .default_value = null,1019 .default_value = null,
1020 .is_comptime = false,1020 .is_comptime = false,
1021 .alignment = if (@sizeOf(T) > 0) @alignOf(T) else 0,1021 .alignment = 0,
1022 };1022 };
1023 }1023 }
10241024
lib/std/zig/AstGen.zig+129-60
...@@ -1711,7 +1711,7 @@ fn structInitExpr(...@@ -1711,7 +1711,7 @@ fn structInitExpr(
1711 return rvalue(gz, ri, val, node);1711 return rvalue(gz, ri, val, node);
1712 },1712 },
1713 .none, .ref, .inferred_ptr => {1713 .none, .ref, .inferred_ptr => {
1714 return rvalue(gz, ri, .empty_struct, node);1714 return rvalue(gz, ri, .empty_tuple, node);
1715 },1715 },
1716 .destructure => |destructure| {1716 .destructure => |destructure| {
1717 return astgen.failNodeNotes(node, "empty initializer cannot be destructured", .{}, &.{1717 return astgen.failNodeNotes(node, "empty initializer cannot be destructured", .{}, &.{
...@@ -1888,6 +1888,8 @@ fn structInitExprAnon(...@@ -1888,6 +1888,8 @@ fn structInitExprAnon(
1888 const tree = astgen.tree;1888 const tree = astgen.tree;
18891889
1890 const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{1890 const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{
1891 .abs_node = node,
1892 .abs_line = astgen.source_line,
1891 .fields_len = @intCast(struct_init.ast.fields.len),1893 .fields_len = @intCast(struct_init.ast.fields.len),
1892 });1894 });
1893 const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).@"struct".fields.len;1895 const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).@"struct".fields.len;
...@@ -1919,6 +1921,8 @@ fn structInitExprTyped(...@@ -1919,6 +1921,8 @@ fn structInitExprTyped(
1919 const tree = astgen.tree;1921 const tree = astgen.tree;
19201922
1921 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{1923 const payload_index = try addExtra(astgen, Zir.Inst.StructInit{
1924 .abs_node = node,
1925 .abs_line = astgen.source_line,
1922 .fields_len = @intCast(struct_init.ast.fields.len),1926 .fields_len = @intCast(struct_init.ast.fields.len),
1923 });1927 });
1924 const field_size = @typeInfo(Zir.Inst.StructInit.Item).@"struct".fields.len;1928 const field_size = @typeInfo(Zir.Inst.StructInit.Item).@"struct".fields.len;
...@@ -5007,6 +5011,25 @@ fn structDeclInner(...@@ -5007,6 +5011,25 @@ fn structDeclInner(
5007 layout: std.builtin.Type.ContainerLayout,5011 layout: std.builtin.Type.ContainerLayout,
5008 backing_int_node: Ast.Node.Index,5012 backing_int_node: Ast.Node.Index,
5009) InnerError!Zir.Inst.Ref {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 const decl_inst = try gz.reserveInstructionIndex();5033 const decl_inst = try gz.reserveInstructionIndex();
50115034
5012 if (container_decl.ast.members.len == 0 and backing_int_node == 0) {5035 if (container_decl.ast.members.len == 0 and backing_int_node == 0) {
...@@ -5019,7 +5042,6 @@ fn structDeclInner(...@@ -5019,7 +5042,6 @@ fn structDeclInner(
5019 .has_backing_int = false,5042 .has_backing_int = false,
5020 .known_non_opv = false,5043 .known_non_opv = false,
5021 .known_comptime_only = false,5044 .known_comptime_only = false,
5022 .is_tuple = false,
5023 .any_comptime_fields = false,5045 .any_comptime_fields = false,
5024 .any_default_inits = false,5046 .any_default_inits = false,
5025 .any_aligned_fields = false,5047 .any_aligned_fields = false,
...@@ -5028,10 +5050,6 @@ fn structDeclInner(...@@ -5028,10 +5050,6 @@ fn structDeclInner(
5028 return decl_inst.toRef();5050 return decl_inst.toRef();
5029 }5051 }
50305052
5031 const astgen = gz.astgen;
5032 const gpa = astgen.gpa;
5033 const tree = astgen.tree;
5034
5035 var namespace: Scope.Namespace = .{5053 var namespace: Scope.Namespace = .{
5036 .parent = scope,5054 .parent = scope,
5037 .node = node,5055 .node = node,
...@@ -5106,46 +5124,6 @@ fn structDeclInner(...@@ -5106,46 +5124,6 @@ fn structDeclInner(
5106 // No defer needed here because it is handled by `wip_members.deinit()` above.5124 // No defer needed here because it is handled by `wip_members.deinit()` above.
5107 const bodies_start = astgen.scratch.items.len;5125 const bodies_start = astgen.scratch.items.len;
51085126
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 const old_hasher = astgen.src_hasher;5127 const old_hasher = astgen.src_hasher;
5150 defer astgen.src_hasher = old_hasher;5128 defer astgen.src_hasher = old_hasher;
5151 astgen.src_hasher = std.zig.SrcHasher.init(.{});5129 astgen.src_hasher = std.zig.SrcHasher.init(.{});
...@@ -5167,16 +5145,10 @@ fn structDeclInner(...@@ -5167,16 +5145,10 @@ fn structDeclInner(
51675145
5168 astgen.src_hasher.update(tree.getNodeSource(member_node));5146 astgen.src_hasher.update(tree.getNodeSource(member_node));
51695147
5170 if (!is_tuple) {5148 const field_name = try astgen.identAsString(member.ast.main_token);
5171 const field_name = try astgen.identAsString(member.ast.main_token);5149 member.convertToNonTupleLike(astgen.tree.nodes);
51725150 assert(!member.ast.tuple_like);
5173 member.convertToNonTupleLike(astgen.tree.nodes);5151 wip_members.appendToField(@intFromEnum(field_name));
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 }
51805152
5181 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());5153 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
5182 wip_members.appendToField(@intFromEnum(doc_comment_index));5154 wip_members.appendToField(@intFromEnum(doc_comment_index));
...@@ -5270,7 +5242,6 @@ fn structDeclInner(...@@ -5270,7 +5242,6 @@ fn structDeclInner(
5270 .has_backing_int = backing_int_ref != .none,5242 .has_backing_int = backing_int_ref != .none,
5271 .known_non_opv = known_non_opv,5243 .known_non_opv = known_non_opv,
5272 .known_comptime_only = known_comptime_only,5244 .known_comptime_only = known_comptime_only,
5273 .is_tuple = is_tuple,
5274 .any_comptime_fields = any_comptime_fields,5245 .any_comptime_fields = any_comptime_fields,
5275 .any_default_inits = any_default_inits,5246 .any_default_inits = any_default_inits,
5276 .any_aligned_fields = any_aligned_fields,5247 .any_aligned_fields = any_aligned_fields,
...@@ -5300,6 +5271,106 @@ fn structDeclInner(...@@ -5300,6 +5271,106 @@ fn structDeclInner(
5300 return decl_inst.toRef();5271 return decl_inst.toRef();
5301}5272}
53025273
5274fn 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
5303fn unionDeclInner(5374fn unionDeclInner(
5304 gz: *GenZir,5375 gz: *GenZir,
5305 scope: *Scope,5376 scope: *Scope,
...@@ -11172,7 +11243,7 @@ fn rvalueInner(...@@ -11172,7 +11243,7 @@ fn rvalueInner(
11172 as_ty | @intFromEnum(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),11243 as_ty | @intFromEnum(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),
11173 as_ty | @intFromEnum(Zir.Inst.Ref.anyerror_void_error_union_type),11244 as_ty | @intFromEnum(Zir.Inst.Ref.anyerror_void_error_union_type),
11174 as_ty | @intFromEnum(Zir.Inst.Ref.generic_poison_type),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 as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero),11247 as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero),
11177 as_comptime_int | @intFromEnum(Zir.Inst.Ref.one),11248 as_comptime_int | @intFromEnum(Zir.Inst.Ref.one),
11178 as_comptime_int | @intFromEnum(Zir.Inst.Ref.negative_one),11249 as_comptime_int | @intFromEnum(Zir.Inst.Ref.negative_one),
...@@ -13173,7 +13244,6 @@ const GenZir = struct {...@@ -13173,7 +13244,6 @@ const GenZir = struct {
13173 layout: std.builtin.Type.ContainerLayout,13244 layout: std.builtin.Type.ContainerLayout,
13174 known_non_opv: bool,13245 known_non_opv: bool,
13175 known_comptime_only: bool,13246 known_comptime_only: bool,
13176 is_tuple: bool,
13177 any_comptime_fields: bool,13247 any_comptime_fields: bool,
13178 any_default_inits: bool,13248 any_default_inits: bool,
13179 any_aligned_fields: bool,13249 any_aligned_fields: bool,
...@@ -13217,7 +13287,6 @@ const GenZir = struct {...@@ -13217,7 +13287,6 @@ const GenZir = struct {
13217 .has_backing_int = args.has_backing_int,13287 .has_backing_int = args.has_backing_int,
13218 .known_non_opv = args.known_non_opv,13288 .known_non_opv = args.known_non_opv,
13219 .known_comptime_only = args.known_comptime_only,13289 .known_comptime_only = args.known_comptime_only,
13220 .is_tuple = args.is_tuple,
13221 .name_strategy = gz.anon_name_strategy,13290 .name_strategy = gz.anon_name_strategy,
13222 .layout = args.layout,13291 .layout = args.layout,
13223 .any_comptime_fields = args.any_comptime_fields,13292 .any_comptime_fields = args.any_comptime_fields,
lib/std/zig/BuiltinFn.zig+4-3
...@@ -1,5 +1,3 @@...@@ -1,5 +1,3 @@
1const std = @import("std");
2
3pub const Tag = enum {1pub const Tag = enum {
4 add_with_overflow,2 add_with_overflow,
5 addrspace_cast,3 addrspace_cast,
...@@ -147,7 +145,7 @@ param_count: ?u8,...@@ -147,7 +145,7 @@ param_count: ?u8,
147145
148pub const list = list: {146pub const list = list: {
149 @setEvalBranchQuota(3000);147 @setEvalBranchQuota(3000);
150 break :list std.StaticStringMap(@This()).initComptime(.{148 break :list std.StaticStringMap(BuiltinFn).initComptime([_]struct { []const u8, BuiltinFn }{
151 .{149 .{
152 "@addWithOverflow",150 "@addWithOverflow",
153 .{151 .{
...@@ -1011,3 +1009,6 @@ pub const list = list: {...@@ -1011,3 +1009,6 @@ pub const list = list: {
1011 },1009 },
1012 });1010 });
1013};1011};
1012
1013const std = @import("std");
1014const BuiltinFn = @This();
lib/std/zig/Zir.zig+69-10
...@@ -1887,6 +1887,10 @@ pub const Inst = struct {...@@ -1887,6 +1887,10 @@ pub const Inst = struct {
1887 /// `operand` is payload index to `OpaqueDecl`.1887 /// `operand` is payload index to `OpaqueDecl`.
1888 /// `small` is `OpaqueDecl.Small`.1888 /// `small` is `OpaqueDecl.Small`.
1889 opaque_decl,1889 opaque_decl,
1890 /// A tuple type. Note that tuples are not namespace/container types.
1891 /// `operand` is payload index to `TupleDecl`.
1892 /// `small` is `fields_len: u16`.
1893 tuple_decl,
1890 /// Implements the `@This` builtin.1894 /// Implements the `@This` builtin.
1891 /// `operand` is `src_node: i32`.1895 /// `operand` is `src_node: i32`.
1892 this,1896 this,
...@@ -2187,7 +2191,7 @@ pub const Inst = struct {...@@ -2187,7 +2191,7 @@ pub const Inst = struct {
2187 anyerror_void_error_union_type,2191 anyerror_void_error_union_type,
2188 adhoc_inferred_error_set_type,2192 adhoc_inferred_error_set_type,
2189 generic_poison_type,2193 generic_poison_type,
2190 empty_struct_type,2194 empty_tuple_type,
2191 undef,2195 undef,
2192 zero,2196 zero,
2193 zero_usize,2197 zero_usize,
...@@ -2202,7 +2206,7 @@ pub const Inst = struct {...@@ -2202,7 +2206,7 @@ pub const Inst = struct {
2202 null_value,2206 null_value,
2203 bool_true,2207 bool_true,
2204 bool_false,2208 bool_false,
2205 empty_struct,2209 empty_tuple,
2206 generic_poison,2210 generic_poison,
22072211
2208 /// This Ref does not correspond to any ZIR instruction or constant2212 /// This Ref does not correspond to any ZIR instruction or constant
...@@ -3041,7 +3045,7 @@ pub const Inst = struct {...@@ -3041,7 +3045,7 @@ pub const Inst = struct {
3041 /// 0b0X00: whether corresponding field is comptime3045 /// 0b0X00: whether corresponding field is comptime
3042 /// 0bX000: whether corresponding field has a type expression3046 /// 0bX000: whether corresponding field has a type expression
3043 /// 9. fields: { // for every fields_len3047 /// 9. fields: { // for every fields_len
3044 /// field_name: u32, // if !is_tuple3048 /// field_name: u32,
3045 /// doc_comment: NullTerminatedString, // .empty if no doc comment3049 /// doc_comment: NullTerminatedString, // .empty if no doc comment
3046 /// field_type: Ref, // if corresponding bit is not set. none means anytype.3050 /// field_type: Ref, // if corresponding bit is not set. none means anytype.
3047 /// field_type_body_len: u32, // if corresponding bit is set3051 /// field_type_body_len: u32, // if corresponding bit is set
...@@ -3071,13 +3075,12 @@ pub const Inst = struct {...@@ -3071,13 +3075,12 @@ pub const Inst = struct {
3071 has_backing_int: bool,3075 has_backing_int: bool,
3072 known_non_opv: bool,3076 known_non_opv: bool,
3073 known_comptime_only: bool,3077 known_comptime_only: bool,
3074 is_tuple: bool,
3075 name_strategy: NameStrategy,3078 name_strategy: NameStrategy,
3076 layout: std.builtin.Type.ContainerLayout,3079 layout: std.builtin.Type.ContainerLayout,
3077 any_default_inits: bool,3080 any_default_inits: bool,
3078 any_comptime_fields: bool,3081 any_comptime_fields: bool,
3079 any_aligned_fields: bool,3082 any_aligned_fields: bool,
3080 _: u2 = undefined,3083 _: u3 = undefined,
3081 };3084 };
3082 };3085 };
30833086
...@@ -3302,6 +3305,15 @@ pub const Inst = struct {...@@ -3302,6 +3305,15 @@ pub const Inst = struct {
3302 };3305 };
3303 };3306 };
33043307
3308 /// Trailing:
3309 /// 1. fields: { // for every `fields_len` (stored in `extended.small`)
3310 /// type: Inst.Ref,
3311 /// init: Inst.Ref, // `.none` for non-`comptime` fields
3312 /// }
3313 pub const TupleDecl = struct {
3314 src_node: i32, // relative
3315 };
3316
3305 /// Trailing:3317 /// Trailing:
3306 /// { // for every fields_len3318 /// { // for every fields_len
3307 /// field_name: NullTerminatedString // null terminated string index3319 /// field_name: NullTerminatedString // null terminated string index
...@@ -3329,6 +3341,11 @@ pub const Inst = struct {...@@ -3329,6 +3341,11 @@ pub const Inst = struct {
33293341
3330 /// Trailing is an item per field.3342 /// Trailing is an item per field.
3331 pub const StructInit = struct {3343 pub const StructInit = struct {
3344 /// If this is an anonymous initialization (the operand is poison), this instruction becomes the owner of a type.
3345 /// To resolve source locations, we need an absolute source node.
3346 abs_node: Ast.Node.Index,
3347 /// Likewise, we need an absolute line number.
3348 abs_line: u32,
3332 fields_len: u32,3349 fields_len: u32,
33333350
3334 pub const Item = struct {3351 pub const Item = struct {
...@@ -3344,6 +3361,11 @@ pub const Inst = struct {...@@ -3344,6 +3361,11 @@ pub const Inst = struct {
3344 /// TODO make this instead array of inits followed by array of names because3361 /// TODO make this instead array of inits followed by array of names because
3345 /// it will be simpler Sema code and better for CPU cache.3362 /// it will be simpler Sema code and better for CPU cache.
3346 pub const StructInitAnon = struct {3363 pub const StructInitAnon = struct {
3364 /// This is an anonymous initialization, meaning this instruction becomes the owner of a type.
3365 /// To resolve source locations, we need an absolute source node.
3366 abs_node: Ast.Node.Index,
3367 /// Likewise, we need an absolute line number.
3368 abs_line: u32,
3347 fields_len: u32,3369 fields_len: u32,
33483370
3349 pub const Item = struct {3371 pub const Item = struct {
...@@ -3741,6 +3763,8 @@ fn findDeclsInner(...@@ -3741,6 +3763,8 @@ fn findDeclsInner(
3741 defers: *std.AutoHashMapUnmanaged(u32, void),3763 defers: *std.AutoHashMapUnmanaged(u32, void),
3742 inst: Inst.Index,3764 inst: Inst.Index,
3743) Allocator.Error!void {3765) Allocator.Error!void {
3766 comptime assert(Zir.inst_tracking_version == 0);
3767
3744 const tags = zir.instructions.items(.tag);3768 const tags = zir.instructions.items(.tag);
3745 const datas = zir.instructions.items(.data);3769 const datas = zir.instructions.items(.data);
37463770
...@@ -3884,9 +3908,6 @@ fn findDeclsInner(...@@ -3884,9 +3908,6 @@ fn findDeclsInner(
3884 .struct_init_empty,3908 .struct_init_empty,
3885 .struct_init_empty_result,3909 .struct_init_empty_result,
3886 .struct_init_empty_ref_result,3910 .struct_init_empty_ref_result,
3887 .struct_init_anon,
3888 .struct_init,
3889 .struct_init_ref,
3890 .validate_struct_init_ty,3911 .validate_struct_init_ty,
3891 .validate_struct_init_result_ty,3912 .validate_struct_init_result_ty,
3892 .validate_ptr_struct_init,3913 .validate_ptr_struct_init,
...@@ -3978,6 +3999,12 @@ fn findDeclsInner(...@@ -3978,6 +3999,12 @@ fn findDeclsInner(
3978 .restore_err_ret_index_fn_entry,3999 .restore_err_ret_index_fn_entry,
3979 => return,4000 => return,
39804001
4002 // Struct initializations need tracking, as they may create anonymous struct types.
4003 .struct_init,
4004 .struct_init_ref,
4005 .struct_init_anon,
4006 => return list.append(gpa, inst),
4007
3981 .extended => {4008 .extended => {
3982 const extended = datas[@intFromEnum(inst)].extended;4009 const extended = datas[@intFromEnum(inst)].extended;
3983 switch (extended.opcode) {4010 switch (extended.opcode) {
...@@ -4034,6 +4061,7 @@ fn findDeclsInner(...@@ -4034,6 +4061,7 @@ fn findDeclsInner(
4034 .builtin_value,4061 .builtin_value,
4035 .branch_hint,4062 .branch_hint,
4036 .inplace_arith_result_ty,4063 .inplace_arith_result_ty,
4064 .tuple_decl,
4037 => return,4065 => return,
40384066
4039 // `@TypeOf` has a body.4067 // `@TypeOf` has a body.
...@@ -4110,8 +4138,7 @@ fn findDeclsInner(...@@ -4110,8 +4138,7 @@ fn findDeclsInner(
4110 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;4138 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
4111 cur_bit_bag >>= 1;4139 cur_bit_bag >>= 1;
41124140
4113 fields_extra_index += @intFromBool(!small.is_tuple); // field_name4141 fields_extra_index += 2; // field_name, doc_comment
4114 fields_extra_index += 1; // doc_comment
41154142
4116 if (has_type_body) {4143 if (has_type_body) {
4117 const field_type_body_len = zir.extra[fields_extra_index];4144 const field_type_body_len = zir.extra[fields_extra_index];
...@@ -4736,3 +4763,35 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {...@@ -4736,3 +4763,35 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash {
4736 else => return null,4763 else => return null,
4737 }4764 }
4738}4765}
4766
4767/// When the ZIR update tracking logic must be modified to consider new instructions,
4768/// change this constant to trigger compile errors at all relevant locations.
4769pub const inst_tracking_version = 0;
4770
4771/// Asserts that a ZIR instruction is tracked across incremental updates, and
4772/// thus may be given an `InternPool.TrackedInst`.
4773pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
4774 comptime assert(Zir.inst_tracking_version == 0);
4775 const inst = zir.instructions.get(@intFromEnum(inst_idx));
4776 switch (inst.tag) {
4777 .struct_init,
4778 .struct_init_ref,
4779 .struct_init_anon,
4780 => {}, // tracked in order, as the owner instructions of anonymous struct types
4781 .func,
4782 .func_inferred,
4783 .func_fancy,
4784 => {}, // tracked in order, as the owner instructions of function bodies
4785 .declaration => {}, // tracked by correlating names in the namespace of the parent container
4786 .extended => switch (inst.data.extended.opcode) {
4787 .struct_decl,
4788 .union_decl,
4789 .enum_decl,
4790 .opaque_decl,
4791 .reify,
4792 => {}, // tracked in order, as the owner instructions of explicit container types
4793 else => unreachable, // assertion failure; not trackable
4794 },
4795 else => unreachable, // assertion failure; not trackable
4796 }
4797}
lib/std/zig/system/darwin/macos.zig+3-3
...@@ -277,7 +277,7 @@ const SystemVersionTokenizer = struct {...@@ -277,7 +277,7 @@ const SystemVersionTokenizer = struct {
277};277};
278278
279test "detect" {279test "detect" {
280 const cases = .{280 const cases: [5]struct { []const u8, std.SemanticVersion } = .{
281 .{281 .{
282 \\<?xml version="1.0" encoding="UTF-8"?>282 \\<?xml version="1.0" encoding="UTF-8"?>
283 \\<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">283 \\<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
...@@ -388,8 +388,8 @@ test "detect" {...@@ -388,8 +388,8 @@ test "detect" {
388388
389 inline for (cases) |case| {389 inline for (cases) |case| {
390 const ver0 = try parseSystemVersion(case[0]);390 const ver0 = try parseSystemVersion(case[0]);
391 const ver1: std.SemanticVersion = case[1];391 const ver1 = case[1];
392 try testing.expectEqual(@as(std.math.Order, .eq), ver0.order(ver1));392 try testing.expectEqual(std.math.Order.eq, ver0.order(ver1));
393 }393 }
394}394}
395395
src/Air.zig+2-2
...@@ -962,7 +962,7 @@ pub const Inst = struct {...@@ -962,7 +962,7 @@ pub const Inst = struct {
962 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),962 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
963 adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type),963 adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type),
964 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),964 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
965 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),965 empty_tuple_type = @intFromEnum(InternPool.Index.empty_tuple_type),
966 undef = @intFromEnum(InternPool.Index.undef),966 undef = @intFromEnum(InternPool.Index.undef),
967 zero = @intFromEnum(InternPool.Index.zero),967 zero = @intFromEnum(InternPool.Index.zero),
968 zero_usize = @intFromEnum(InternPool.Index.zero_usize),968 zero_usize = @intFromEnum(InternPool.Index.zero_usize),
...@@ -977,7 +977,7 @@ pub const Inst = struct {...@@ -977,7 +977,7 @@ pub const Inst = struct {
977 null_value = @intFromEnum(InternPool.Index.null_value),977 null_value = @intFromEnum(InternPool.Index.null_value),
978 bool_true = @intFromEnum(InternPool.Index.bool_true),978 bool_true = @intFromEnum(InternPool.Index.bool_true),
979 bool_false = @intFromEnum(InternPool.Index.bool_false),979 bool_false = @intFromEnum(InternPool.Index.bool_false),
980 empty_struct = @intFromEnum(InternPool.Index.empty_struct),980 empty_tuple = @intFromEnum(InternPool.Index.empty_tuple),
981 generic_poison = @intFromEnum(InternPool.Index.generic_poison),981 generic_poison = @intFromEnum(InternPool.Index.generic_poison),
982982
983 /// This Ref does not correspond to any AIR instruction or constant983 /// This Ref does not correspond to any AIR instruction or constant
src/Air/types_resolved.zig+1-1
...@@ -501,7 +501,7 @@ pub fn checkType(ty: Type, zcu: *Zcu) bool {...@@ -501,7 +501,7 @@ pub fn checkType(ty: Type, zcu: *Zcu) bool {
501 .auto, .@"extern" => struct_obj.flagsUnordered(ip).fully_resolved,501 .auto, .@"extern" => struct_obj.flagsUnordered(ip).fully_resolved,
502 };502 };
503 },503 },
504 .anon_struct_type => |tuple| {504 .tuple_type => |tuple| {
505 for (0..tuple.types.len) |i| {505 for (0..tuple.types.len) |i| {
506 const field_is_comptime = tuple.values.get(ip)[i] != .none;506 const field_is_comptime = tuple.values.get(ip)[i] != .none;
507 if (field_is_comptime) continue;507 if (field_is_comptime) continue;
src/Compilation.zig+1-1
...@@ -2081,7 +2081,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2081,7 +2081,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2081 log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name});2081 log.debug("CacheMode.whole cache miss for {s}", .{comp.root_name});
20822082
2083 // Compile the artifacts to a temporary directory.2083 // Compile the artifacts to a temporary directory.
2084 const tmp_artifact_directory = d: {2084 const tmp_artifact_directory: Directory = d: {
2085 const s = std.fs.path.sep_str;2085 const s = std.fs.path.sep_str;
2086 tmp_dir_rand_int = std.crypto.random.int(u64);2086 tmp_dir_rand_int = std.crypto.random.int(u64);
2087 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);2087 const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
src/InternPool.zig+109-230
...@@ -1787,10 +1787,11 @@ pub const Key = union(enum) {...@@ -1787,10 +1787,11 @@ pub const Key = union(enum) {
1787 /// or was created with `@Type`. It is unique and based on a declaration.1787 /// or was created with `@Type`. It is unique and based on a declaration.
1788 /// It may be a tuple, if declared like this: `struct {A, B, C}`.1788 /// It may be a tuple, if declared like this: `struct {A, B, C}`.
1789 struct_type: NamespaceType,1789 struct_type: NamespaceType,
1790 /// This is an anonymous struct or tuple type which has no corresponding1790 /// This is a tuple type. Tuples are logically similar to structs, but have some
1791 /// declaration. It is used for types that have no `struct` keyword in the1791 /// important differences in semantics; they do not undergo staged type resolution,
1792 /// source code, and were not created via `@Type`.1792 /// so cannot be self-referential, and they are not considered container/namespace
1793 anon_struct_type: AnonStructType,1793 /// types, so cannot have declarations and have structural equality properties.
1794 tuple_type: TupleType,
1794 union_type: NamespaceType,1795 union_type: NamespaceType,
1795 opaque_type: NamespaceType,1796 opaque_type: NamespaceType,
1796 enum_type: NamespaceType,1797 enum_type: NamespaceType,
...@@ -1919,27 +1920,10 @@ pub const Key = union(enum) {...@@ -1919,27 +1920,10 @@ pub const Key = union(enum) {
1919 child: Index,1920 child: Index,
1920 };1921 };
19211922
1922 pub const AnonStructType = struct {1923 pub const TupleType = struct {
1923 types: Index.Slice,1924 types: Index.Slice,
1924 /// This may be empty, indicating this is a tuple.
1925 names: NullTerminatedString.Slice,
1926 /// These elements may be `none`, indicating runtime-known.1925 /// These elements may be `none`, indicating runtime-known.
1927 values: Index.Slice,1926 values: Index.Slice,
1928
1929 pub fn isTuple(self: AnonStructType) bool {
1930 return self.names.len == 0;
1931 }
1932
1933 pub fn fieldName(
1934 self: AnonStructType,
1935 ip: *const InternPool,
1936 index: usize,
1937 ) OptionalNullTerminatedString {
1938 if (self.names.len == 0)
1939 return .none;
1940
1941 return self.names.get(ip)[index].toOptional();
1942 }
1943 };1927 };
19441928
1945 /// This is the hashmap key. To fetch other data associated with the type, see:1929 /// This is the hashmap key. To fetch other data associated with the type, see:
...@@ -1965,18 +1949,15 @@ pub const Key = union(enum) {...@@ -1965,18 +1949,15 @@ pub const Key = union(enum) {
1965 /// The union for which this is a tag type.1949 /// The union for which this is a tag type.
1966 union_type: Index,1950 union_type: Index,
1967 },1951 },
1968 /// This type originates from a reification via `@Type`.1952 /// This type originates from a reification via `@Type`, or from an anonymous initialization.
1969 /// It is hased based on its ZIR instruction index and fields, attributes, etc.1953 /// It is hashed based on its ZIR instruction index and fields, attributes, etc.
1970 /// To avoid making this key overly complex, the type-specific data is hased by Sema.1954 /// To avoid making this key overly complex, the type-specific data is hased by Sema.
1971 reified: struct {1955 reified: struct {
1972 /// A `reify` instruction.1956 /// A `reify`, `struct_init`, `struct_init_ref`, or `struct_init_anon` instruction.
1973 zir_index: TrackedInst.Index,1957 zir_index: TrackedInst.Index,
1974 /// A hash of this type's attributes, fields, etc, generated by Sema.1958 /// A hash of this type's attributes, fields, etc, generated by Sema.
1975 type_hash: u64,1959 type_hash: u64,
1976 },1960 },
1977 /// This type is `@TypeOf(.{})`.
1978 /// TODO: can we change the language spec to not special-case this type?
1979 empty_struct: void,
1980 };1961 };
19811962
1982 pub const FuncType = struct {1963 pub const FuncType = struct {
...@@ -2497,7 +2478,6 @@ pub const Key = union(enum) {...@@ -2497,7 +2478,6 @@ pub const Key = union(enum) {
2497 std.hash.autoHash(&hasher, reified.zir_index);2478 std.hash.autoHash(&hasher, reified.zir_index);
2498 std.hash.autoHash(&hasher, reified.type_hash);2479 std.hash.autoHash(&hasher, reified.type_hash);
2499 },2480 },
2500 .empty_struct => {},
2501 }2481 }
2502 return hasher.final();2482 return hasher.final();
2503 },2483 },
...@@ -2570,7 +2550,7 @@ pub const Key = union(enum) {...@@ -2570,7 +2550,7 @@ pub const Key = union(enum) {
2570 const child = switch (ip.indexToKey(aggregate.ty)) {2550 const child = switch (ip.indexToKey(aggregate.ty)) {
2571 .array_type => |array_type| array_type.child,2551 .array_type => |array_type| array_type.child,
2572 .vector_type => |vector_type| vector_type.child,2552 .vector_type => |vector_type| vector_type.child,
2573 .anon_struct_type, .struct_type => .none,2553 .tuple_type, .struct_type => .none,
2574 else => unreachable,2554 else => unreachable,
2575 };2555 };
25762556
...@@ -2625,11 +2605,10 @@ pub const Key = union(enum) {...@@ -2625,11 +2605,10 @@ pub const Key = union(enum) {
26252605
2626 .error_set_type => |x| Hash.hash(seed, std.mem.sliceAsBytes(x.names.get(ip))),2606 .error_set_type => |x| Hash.hash(seed, std.mem.sliceAsBytes(x.names.get(ip))),
26272607
2628 .anon_struct_type => |anon_struct_type| {2608 .tuple_type => |tuple_type| {
2629 var hasher = Hash.init(seed);2609 var hasher = Hash.init(seed);
2630 for (anon_struct_type.types.get(ip)) |elem| std.hash.autoHash(&hasher, elem);2610 for (tuple_type.types.get(ip)) |elem| std.hash.autoHash(&hasher, elem);
2631 for (anon_struct_type.values.get(ip)) |elem| std.hash.autoHash(&hasher, elem);2611 for (tuple_type.values.get(ip)) |elem| std.hash.autoHash(&hasher, elem);
2632 for (anon_struct_type.names.get(ip)) |elem| std.hash.autoHash(&hasher, elem);
2633 return hasher.final();2612 return hasher.final();
2634 },2613 },
26352614
...@@ -2929,7 +2908,6 @@ pub const Key = union(enum) {...@@ -2929,7 +2908,6 @@ pub const Key = union(enum) {
2929 return a_r.zir_index == b_r.zir_index and2908 return a_r.zir_index == b_r.zir_index and
2930 a_r.type_hash == b_r.type_hash;2909 a_r.type_hash == b_r.type_hash;
2931 },2910 },
2932 .empty_struct => return true,
2933 }2911 }
2934 },2912 },
2935 .aggregate => |a_info| {2913 .aggregate => |a_info| {
...@@ -2981,11 +2959,10 @@ pub const Key = union(enum) {...@@ -2981,11 +2959,10 @@ pub const Key = union(enum) {
2981 },2959 },
2982 }2960 }
2983 },2961 },
2984 .anon_struct_type => |a_info| {2962 .tuple_type => |a_info| {
2985 const b_info = b.anon_struct_type;2963 const b_info = b.tuple_type;
2986 return std.mem.eql(Index, a_info.types.get(ip), b_info.types.get(ip)) and2964 return std.mem.eql(Index, a_info.types.get(ip), b_info.types.get(ip)) and
2987 std.mem.eql(Index, a_info.values.get(ip), b_info.values.get(ip)) and2965 std.mem.eql(Index, a_info.values.get(ip), b_info.values.get(ip));
2988 std.mem.eql(NullTerminatedString, a_info.names.get(ip), b_info.names.get(ip));
2989 },2966 },
2990 .error_set_type => |a_info| {2967 .error_set_type => |a_info| {
2991 const b_info = b.error_set_type;2968 const b_info = b.error_set_type;
...@@ -3025,7 +3002,7 @@ pub const Key = union(enum) {...@@ -3025,7 +3002,7 @@ pub const Key = union(enum) {
3025 .union_type,3002 .union_type,
3026 .opaque_type,3003 .opaque_type,
3027 .enum_type,3004 .enum_type,
3028 .anon_struct_type,3005 .tuple_type,
3029 .func_type,3006 .func_type,
3030 => .type_type,3007 => .type_type,
30313008
...@@ -3054,7 +3031,7 @@ pub const Key = union(enum) {...@@ -3054,7 +3031,7 @@ pub const Key = union(enum) {
3054 .void => .void_type,3031 .void => .void_type,
3055 .null => .null_type,3032 .null => .null_type,
3056 .false, .true => .bool_type,3033 .false, .true => .bool_type,
3057 .empty_struct => .empty_struct_type,3034 .empty_tuple => .empty_tuple_type,
3058 .@"unreachable" => .noreturn_type,3035 .@"unreachable" => .noreturn_type,
3059 .generic_poison => .generic_poison_type,3036 .generic_poison => .generic_poison_type,
3060 },3037 },
...@@ -3411,13 +3388,11 @@ pub const LoadedStructType = struct {...@@ -3411,13 +3388,11 @@ pub const LoadedStructType = struct {
3411 // TODO: the non-fqn will be needed by the new dwarf structure3388 // TODO: the non-fqn will be needed by the new dwarf structure
3412 /// The name of this struct type.3389 /// The name of this struct type.
3413 name: NullTerminatedString,3390 name: NullTerminatedString,
3414 /// The `Cau` within which type resolution occurs. `none` when the struct is `@TypeOf(.{})`.3391 /// The `Cau` within which type resolution occurs.
3415 cau: Cau.Index.Optional,3392 cau: Cau.Index,
3416 /// `none` when the struct is `@TypeOf(.{})`.3393 namespace: NamespaceIndex,
3417 namespace: OptionalNamespaceIndex,
3418 /// Index of the `struct_decl` or `reify` ZIR instruction.3394 /// Index of the `struct_decl` or `reify` ZIR instruction.
3419 /// Only `none` when the struct is `@TypeOf(.{})`.3395 zir_index: TrackedInst.Index,
3420 zir_index: TrackedInst.Index.Optional,
3421 layout: std.builtin.Type.ContainerLayout,3396 layout: std.builtin.Type.ContainerLayout,
3422 field_names: NullTerminatedString.Slice,3397 field_names: NullTerminatedString.Slice,
3423 field_types: Index.Slice,3398 field_types: Index.Slice,
...@@ -3913,10 +3888,6 @@ pub const LoadedStructType = struct {...@@ -3913,10 +3888,6 @@ pub const LoadedStructType = struct {
3913 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);3888 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3914 }3889 }
39153890
3916 pub fn isTuple(s: LoadedStructType, ip: *InternPool) bool {
3917 return s.layout != .@"packed" and s.flagsUnordered(ip).is_tuple;
3918 }
3919
3920 pub fn hasReorderedFields(s: LoadedStructType) bool {3891 pub fn hasReorderedFields(s: LoadedStructType) bool {
3921 return s.layout == .auto;3892 return s.layout == .auto;
3922 }3893 }
...@@ -4008,24 +3979,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4008,24 +3979,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4008 const item = unwrapped_index.getItem(ip);3979 const item = unwrapped_index.getItem(ip);
4009 switch (item.tag) {3980 switch (item.tag) {
4010 .type_struct => {3981 .type_struct => {
4011 if (item.data == 0) return .{
4012 .tid = .main,
4013 .extra_index = 0,
4014 .name = .empty,
4015 .cau = .none,
4016 .namespace = .none,
4017 .zir_index = .none,
4018 .layout = .auto,
4019 .field_names = NullTerminatedString.Slice.empty,
4020 .field_types = Index.Slice.empty,
4021 .field_inits = Index.Slice.empty,
4022 .field_aligns = Alignment.Slice.empty,
4023 .runtime_order = LoadedStructType.RuntimeOrder.Slice.empty,
4024 .comptime_bits = LoadedStructType.ComptimeBits.empty,
4025 .offsets = LoadedStructType.Offsets.empty,
4026 .names_map = .none,
4027 .captures = CaptureValue.Slice.empty,
4028 };
4029 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);3982 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);
4030 const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "cau").?]);3983 const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "cau").?]);
4031 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);3984 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);
...@@ -4045,7 +3998,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4045,7 +3998,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4045 };3998 };
4046 extra_index += captures_len;3999 extra_index += captures_len;
4047 if (flags.is_reified) {4000 if (flags.is_reified) {
4048 extra_index += 2; // PackedU644001 extra_index += 2; // type_hash: PackedU64
4049 }4002 }
4050 const field_types: Index.Slice = .{4003 const field_types: Index.Slice = .{
4051 .tid = unwrapped_index.tid,4004 .tid = unwrapped_index.tid,
...@@ -4053,7 +4006,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4053,7 +4006,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4053 .len = fields_len,4006 .len = fields_len,
4054 };4007 };
4055 extra_index += fields_len;4008 extra_index += fields_len;
4056 const names_map: OptionalMapIndex, const names = if (!flags.is_tuple) n: {4009 const names_map: OptionalMapIndex, const names = n: {
4057 const names_map: OptionalMapIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);4010 const names_map: OptionalMapIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
4058 extra_index += 1;4011 extra_index += 1;
4059 const names: NullTerminatedString.Slice = .{4012 const names: NullTerminatedString.Slice = .{
...@@ -4063,7 +4016,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4063,7 +4016,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4063 };4016 };
4064 extra_index += fields_len;4017 extra_index += fields_len;
4065 break :n .{ names_map, names };4018 break :n .{ names_map, names };
4066 } else .{ .none, NullTerminatedString.Slice.empty };4019 };
4067 const inits: Index.Slice = if (flags.any_default_inits) i: {4020 const inits: Index.Slice = if (flags.any_default_inits) i: {
4068 const inits: Index.Slice = .{4021 const inits: Index.Slice = .{
4069 .tid = unwrapped_index.tid,4022 .tid = unwrapped_index.tid,
...@@ -4114,9 +4067,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4114,9 +4067,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4114 .tid = unwrapped_index.tid,4067 .tid = unwrapped_index.tid,
4115 .extra_index = item.data,4068 .extra_index = item.data,
4116 .name = name,4069 .name = name,
4117 .cau = cau.toOptional(),4070 .cau = cau,
4118 .namespace = namespace.toOptional(),4071 .namespace = namespace,
4119 .zir_index = zir_index.toOptional(),4072 .zir_index = zir_index,
4120 .layout = if (flags.is_extern) .@"extern" else .auto,4073 .layout = if (flags.is_extern) .@"extern" else .auto,
4121 .field_names = names,4074 .field_names = names,
4122 .field_types = field_types,4075 .field_types = field_types,
...@@ -4178,9 +4131,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4178,9 +4131,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4178 .tid = unwrapped_index.tid,4131 .tid = unwrapped_index.tid,
4179 .extra_index = item.data,4132 .extra_index = item.data,
4180 .name = name,4133 .name = name,
4181 .cau = cau.toOptional(),4134 .cau = cau,
4182 .namespace = namespace.toOptional(),4135 .namespace = namespace,
4183 .zir_index = zir_index.toOptional(),4136 .zir_index = zir_index,
4184 .layout = .@"packed",4137 .layout = .@"packed",
4185 .field_names = field_names,4138 .field_names = field_names,
4186 .field_types = field_types,4139 .field_types = field_types,
...@@ -4407,9 +4360,9 @@ pub const Item = struct {...@@ -4407,9 +4360,9 @@ pub const Item = struct {
4407/// `primitives` in AstGen.zig.4360/// `primitives` in AstGen.zig.
4408pub const Index = enum(u32) {4361pub const Index = enum(u32) {
4409 pub const first_type: Index = .u0_type;4362 pub const first_type: Index = .u0_type;
4410 pub const last_type: Index = .empty_struct_type;4363 pub const last_type: Index = .empty_tuple_type;
4411 pub const first_value: Index = .undef;4364 pub const first_value: Index = .undef;
4412 pub const last_value: Index = .empty_struct;4365 pub const last_value: Index = .empty_tuple;
44134366
4414 u0_type,4367 u0_type,
4415 i0_type,4368 i0_type,
...@@ -4466,8 +4419,9 @@ pub const Index = enum(u32) {...@@ -4466,8 +4419,9 @@ pub const Index = enum(u32) {
4466 /// Used for the inferred error set of inline/comptime function calls.4419 /// Used for the inferred error set of inline/comptime function calls.
4467 adhoc_inferred_error_set_type,4420 adhoc_inferred_error_set_type,
4468 generic_poison_type,4421 generic_poison_type,
4469 /// `@TypeOf(.{})`4422 /// `@TypeOf(.{})`; a tuple with zero elements.
4470 empty_struct_type,4423 /// This is not the same as `struct {}`, since that is a struct rather than a tuple.
4424 empty_tuple_type,
44714425
4472 /// `undefined` (untyped)4426 /// `undefined` (untyped)
4473 undef,4427 undef,
...@@ -4497,8 +4451,8 @@ pub const Index = enum(u32) {...@@ -4497,8 +4451,8 @@ pub const Index = enum(u32) {
4497 bool_true,4451 bool_true,
4498 /// `false`4452 /// `false`
4499 bool_false,4453 bool_false,
4500 /// `.{}` (untyped)4454 /// `.{}`
4501 empty_struct,4455 empty_tuple,
45024456
4503 /// Used for generic parameters where the type and value4457 /// Used for generic parameters where the type and value
4504 /// is not known until generic function instantiation.4458 /// is not known until generic function instantiation.
...@@ -4606,16 +4560,14 @@ pub const Index = enum(u32) {...@@ -4606,16 +4560,14 @@ pub const Index = enum(u32) {
4606 values: []Index,4560 values: []Index,
4607 },4561 },
4608 };4562 };
4609 const DataIsExtraIndexOfTypeStructAnon = struct {4563 const DataIsExtraIndexOfTypeTuple = struct {
4610 const @"data.fields_len" = opaque {};4564 const @"data.fields_len" = opaque {};
4611 data: *TypeStructAnon,4565 data: *TypeTuple,
4612 @"trailing.types.len": *@"data.fields_len",4566 @"trailing.types.len": *@"data.fields_len",
4613 @"trailing.values.len": *@"data.fields_len",4567 @"trailing.values.len": *@"data.fields_len",
4614 @"trailing.names.len": *@"data.fields_len",
4615 trailing: struct {4568 trailing: struct {
4616 types: []Index,4569 types: []Index,
4617 values: []Index,4570 values: []Index,
4618 names: []NullTerminatedString,
4619 },4571 },
4620 };4572 };
46214573
...@@ -4649,10 +4601,9 @@ pub const Index = enum(u32) {...@@ -4649,10 +4601,9 @@ pub const Index = enum(u32) {
4649 simple_type: void,4601 simple_type: void,
4650 type_opaque: struct { data: *Tag.TypeOpaque },4602 type_opaque: struct { data: *Tag.TypeOpaque },
4651 type_struct: struct { data: *Tag.TypeStruct },4603 type_struct: struct { data: *Tag.TypeStruct },
4652 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
4653 type_struct_packed: struct { data: *Tag.TypeStructPacked },4604 type_struct_packed: struct { data: *Tag.TypeStructPacked },
4654 type_struct_packed_inits: struct { data: *Tag.TypeStructPacked },4605 type_struct_packed_inits: struct { data: *Tag.TypeStructPacked },
4655 type_tuple_anon: DataIsExtraIndexOfTypeStructAnon,4606 type_tuple: DataIsExtraIndexOfTypeTuple,
4656 type_union: struct { data: *Tag.TypeUnion },4607 type_union: struct { data: *Tag.TypeUnion },
4657 type_function: struct {4608 type_function: struct {
4658 const @"data.flags.has_comptime_bits" = opaque {};4609 const @"data.flags.has_comptime_bits" = opaque {};
...@@ -4936,11 +4887,10 @@ pub const static_keys = [_]Key{...@@ -4936,11 +4887,10 @@ pub const static_keys = [_]Key{
4936 // generic_poison_type4887 // generic_poison_type
4937 .{ .simple_type = .generic_poison },4888 .{ .simple_type = .generic_poison },
49384889
4939 // empty_struct_type4890 // empty_tuple_type
4940 .{ .anon_struct_type = .{4891 .{ .tuple_type = .{
4941 .types = Index.Slice.empty,4892 .types = .empty,
4942 .names = NullTerminatedString.Slice.empty,4893 .values = .empty,
4943 .values = Index.Slice.empty,
4944 } },4894 } },
49454895
4946 .{ .simple_value = .undefined },4896 .{ .simple_value = .undefined },
...@@ -4991,7 +4941,7 @@ pub const static_keys = [_]Key{...@@ -4991,7 +4941,7 @@ pub const static_keys = [_]Key{
4991 .{ .simple_value = .null },4941 .{ .simple_value = .null },
4992 .{ .simple_value = .true },4942 .{ .simple_value = .true },
4993 .{ .simple_value = .false },4943 .{ .simple_value = .false },
4994 .{ .simple_value = .empty_struct },4944 .{ .simple_value = .empty_tuple },
4995 .{ .simple_value = .generic_poison },4945 .{ .simple_value = .generic_poison },
4996};4946};
49974947
...@@ -5071,20 +5021,16 @@ pub const Tag = enum(u8) {...@@ -5071,20 +5021,16 @@ pub const Tag = enum(u8) {
5071 type_opaque,5021 type_opaque,
5072 /// A non-packed struct type.5022 /// A non-packed struct type.
5073 /// data is 0 or extra index of `TypeStruct`.5023 /// data is 0 or extra index of `TypeStruct`.
5074 /// data == 0 represents `@TypeOf(.{})`.
5075 type_struct,5024 type_struct,
5076 /// An AnonStructType which stores types, names, and values for fields.
5077 /// data is extra index of `TypeStructAnon`.
5078 type_struct_anon,
5079 /// A packed struct, no fields have any init values.5025 /// A packed struct, no fields have any init values.
5080 /// data is extra index of `TypeStructPacked`.5026 /// data is extra index of `TypeStructPacked`.
5081 type_struct_packed,5027 type_struct_packed,
5082 /// A packed struct, one or more fields have init values.5028 /// A packed struct, one or more fields have init values.
5083 /// data is extra index of `TypeStructPacked`.5029 /// data is extra index of `TypeStructPacked`.
5084 type_struct_packed_inits,5030 type_struct_packed_inits,
5085 /// An AnonStructType which has only types and values for fields.5031 /// A `TupleType`.
5086 /// data is extra index of `TypeStructAnon`.5032 /// data is extra index of `TypeTuple`.
5087 type_tuple_anon,5033 type_tuple,
5088 /// A union type.5034 /// A union type.
5089 /// `data` is extra index of `TypeUnion`.5035 /// `data` is extra index of `TypeUnion`.
5090 type_union,5036 type_union,
...@@ -5299,9 +5245,8 @@ pub const Tag = enum(u8) {...@@ -5299,9 +5245,8 @@ pub const Tag = enum(u8) {
5299 .simple_type => unreachable,5245 .simple_type => unreachable,
5300 .type_opaque => TypeOpaque,5246 .type_opaque => TypeOpaque,
5301 .type_struct => TypeStruct,5247 .type_struct => TypeStruct,
5302 .type_struct_anon => TypeStructAnon,
5303 .type_struct_packed, .type_struct_packed_inits => TypeStructPacked,5248 .type_struct_packed, .type_struct_packed_inits => TypeStructPacked,
5304 .type_tuple_anon => TypeStructAnon,5249 .type_tuple => TypeTuple,
5305 .type_union => TypeUnion,5250 .type_union => TypeUnion,
5306 .type_function => TypeFunction,5251 .type_function => TypeFunction,
53075252
...@@ -5546,18 +5491,15 @@ pub const Tag = enum(u8) {...@@ -5546,18 +5491,15 @@ pub const Tag = enum(u8) {
5546 /// 1. capture: CaptureValue // for each `captures_len`5491 /// 1. capture: CaptureValue // for each `captures_len`
5547 /// 2. type_hash: PackedU64 // if `is_reified`5492 /// 2. type_hash: PackedU64 // if `is_reified`
5548 /// 3. type: Index for each field in declared order5493 /// 3. type: Index for each field in declared order
5549 /// 4. if not is_tuple:5494 /// 4. if any_default_inits:
5550 /// names_map: MapIndex,
5551 /// name: NullTerminatedString // for each field in declared order
5552 /// 5. if any_default_inits:
5553 /// init: Index // for each field in declared order5495 /// init: Index // for each field in declared order
5554 /// 6. if any_aligned_fields:5496 /// 5. if any_aligned_fields:
5555 /// align: Alignment // for each field in declared order5497 /// align: Alignment // for each field in declared order
5556 /// 7. if any_comptime_fields:5498 /// 6. if any_comptime_fields:
5557 /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 05499 /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0
5558 /// 8. if not is_extern:5500 /// 7. if not is_extern:
5559 /// field_index: RuntimeOrder // for each field in runtime order5501 /// field_index: RuntimeOrder // for each field in runtime order
5560 /// 9. field_offset: u32 // for each field in declared order, undef until layout_resolved5502 /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved
5561 pub const TypeStruct = struct {5503 pub const TypeStruct = struct {
5562 name: NullTerminatedString,5504 name: NullTerminatedString,
5563 cau: Cau.Index,5505 cau: Cau.Index,
...@@ -5572,7 +5514,6 @@ pub const Tag = enum(u8) {...@@ -5572,7 +5514,6 @@ pub const Tag = enum(u8) {
5572 is_extern: bool = false,5514 is_extern: bool = false,
5573 known_non_opv: bool = false,5515 known_non_opv: bool = false,
5574 requires_comptime: RequiresComptime = @enumFromInt(0),5516 requires_comptime: RequiresComptime = @enumFromInt(0),
5575 is_tuple: bool = false,
5576 assumed_runtime_bits: bool = false,5517 assumed_runtime_bits: bool = false,
5577 assumed_pointer_aligned: bool = false,5518 assumed_pointer_aligned: bool = false,
5578 any_comptime_fields: bool = false,5519 any_comptime_fields: bool = false,
...@@ -5597,7 +5538,7 @@ pub const Tag = enum(u8) {...@@ -5597,7 +5538,7 @@ pub const Tag = enum(u8) {
5597 // which `layout_resolved` does not ensure.5538 // which `layout_resolved` does not ensure.
5598 fully_resolved: bool = false,5539 fully_resolved: bool = false,
5599 is_reified: bool = false,5540 is_reified: bool = false,
5600 _: u7 = 0,5541 _: u8 = 0,
5601 };5542 };
5602 };5543 };
56035544
...@@ -5659,9 +5600,7 @@ pub const Repeated = struct {...@@ -5659,9 +5600,7 @@ pub const Repeated = struct {
5659/// Trailing:5600/// Trailing:
5660/// 0. type: Index for each fields_len5601/// 0. type: Index for each fields_len
5661/// 1. value: Index for each fields_len5602/// 1. value: Index for each fields_len
5662/// 2. name: NullTerminatedString for each fields_len5603pub const TypeTuple = struct {
5663/// The set of field names is omitted when the `Tag` is `type_tuple_anon`.
5664pub const TypeStructAnon = struct {
5665 fields_len: u32,5604 fields_len: u32,
5666};5605};
56675606
...@@ -5708,8 +5647,8 @@ pub const SimpleValue = enum(u32) {...@@ -5708,8 +5647,8 @@ pub const SimpleValue = enum(u32) {
5708 void = @intFromEnum(Index.void_value),5647 void = @intFromEnum(Index.void_value),
5709 /// This is untyped `null`.5648 /// This is untyped `null`.
5710 null = @intFromEnum(Index.null_value),5649 null = @intFromEnum(Index.null_value),
5711 /// This is the untyped empty struct literal: `.{}`5650 /// This is the untyped empty struct/array literal: `.{}`
5712 empty_struct = @intFromEnum(Index.empty_struct),5651 empty_tuple = @intFromEnum(Index.empty_tuple),
5713 true = @intFromEnum(Index.bool_true),5652 true = @intFromEnum(Index.bool_true),
5714 false = @intFromEnum(Index.bool_false),5653 false = @intFromEnum(Index.bool_false),
5715 @"unreachable" = @intFromEnum(Index.unreachable_value),5654 @"unreachable" = @intFromEnum(Index.unreachable_value),
...@@ -6266,11 +6205,10 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -6266,11 +6205,10 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
6266 // This inserts all the statically-known values into the intern pool in the6205 // This inserts all the statically-known values into the intern pool in the
6267 // order expected.6206 // order expected.
6268 for (&static_keys, 0..) |key, key_index| switch (@as(Index, @enumFromInt(key_index))) {6207 for (&static_keys, 0..) |key, key_index| switch (@as(Index, @enumFromInt(key_index))) {
6269 .empty_struct_type => assert(try ip.getAnonStructType(gpa, .main, .{6208 .empty_tuple_type => assert(try ip.getTupleType(gpa, .main, .{
6270 .types = &.{},6209 .types = &.{},
6271 .names = &.{},
6272 .values = &.{},6210 .values = &.{},
6273 }) == .empty_struct_type),6211 }) == .empty_tuple_type),
6274 else => |expected_index| assert(try ip.get(gpa, .main, key) == expected_index),6212 else => |expected_index| assert(try ip.get(gpa, .main, key) == expected_index),
6275 };6213 };
62766214
...@@ -6412,7 +6350,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6412,7 +6350,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6412 } },6350 } },
64136351
6414 .type_struct => .{ .struct_type = ns: {6352 .type_struct => .{ .struct_type = ns: {
6415 if (data == 0) break :ns .empty_struct;
6416 const extra_list = unwrapped_index.getExtra(ip);6353 const extra_list = unwrapped_index.getExtra(ip);
6417 const extra_items = extra_list.view().items(.@"0");6354 const extra_items = extra_list.view().items(.@"0");
6418 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);6355 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
...@@ -6457,8 +6394,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6457,8 +6394,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6457 } else CaptureValue.Slice.empty },6394 } else CaptureValue.Slice.empty },
6458 } };6395 } };
6459 } },6396 } },
6460 .type_struct_anon => .{ .anon_struct_type = extraTypeStructAnon(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },6397 .type_tuple => .{ .tuple_type = extraTypeTuple(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },
6461 .type_tuple_anon => .{ .anon_struct_type = extraTypeTupleAnon(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },
6462 .type_union => .{ .union_type = ns: {6398 .type_union => .{ .union_type = ns: {
6463 const extra_list = unwrapped_index.getExtra(ip);6399 const extra_list = unwrapped_index.getExtra(ip);
6464 const extra = extraDataTrail(extra_list, Tag.TypeUnion, data);6400 const extra = extraDataTrail(extra_list, Tag.TypeUnion, data);
...@@ -6764,10 +6700,10 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6764,10 +6700,10 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
67646700
6765 // There is only one possible value precisely due to the6701 // There is only one possible value precisely due to the
6766 // fact that this values slice is fully populated!6702 // fact that this values slice is fully populated!
6767 .type_struct_anon, .type_tuple_anon => {6703 .type_tuple => {
6768 const type_struct_anon = extraDataTrail(ty_extra, TypeStructAnon, ty_item.data);6704 const type_tuple = extraDataTrail(ty_extra, TypeTuple, ty_item.data);
6769 const fields_len = type_struct_anon.data.fields_len;6705 const fields_len = type_tuple.data.fields_len;
6770 const values = ty_extra.view().items(.@"0")[type_struct_anon.end + fields_len ..][0..fields_len];6706 const values = ty_extra.view().items(.@"0")[type_tuple.end + fields_len ..][0..fields_len];
6771 return .{ .aggregate = .{6707 return .{ .aggregate = .{
6772 .ty = ty,6708 .ty = ty,
6773 .storage = .{ .elems = @ptrCast(values) },6709 .storage = .{ .elems = @ptrCast(values) },
...@@ -6850,47 +6786,20 @@ fn extraErrorSet(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke...@@ -6850,47 +6786,20 @@ fn extraErrorSet(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
6850 };6786 };
6851}6787}
68526788
6853fn extraTypeStructAnon(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.AnonStructType {6789fn extraTypeTuple(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.TupleType {
6854 const type_struct_anon = extraDataTrail(extra, TypeStructAnon, extra_index);6790 const type_tuple = extraDataTrail(extra, TypeTuple, extra_index);
6855 const fields_len = type_struct_anon.data.fields_len;6791 const fields_len = type_tuple.data.fields_len;
6856 return .{6792 return .{
6857 .types = .{6793 .types = .{
6858 .tid = tid,6794 .tid = tid,
6859 .start = type_struct_anon.end,6795 .start = type_tuple.end,
6860 .len = fields_len,6796 .len = fields_len,
6861 },6797 },
6862 .values = .{6798 .values = .{
6863 .tid = tid,6799 .tid = tid,
6864 .start = type_struct_anon.end + fields_len,6800 .start = type_tuple.end + fields_len,
6865 .len = fields_len,6801 .len = fields_len,
6866 },6802 },
6867 .names = .{
6868 .tid = tid,
6869 .start = type_struct_anon.end + fields_len + fields_len,
6870 .len = fields_len,
6871 },
6872 };
6873}
6874
6875fn extraTypeTupleAnon(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.AnonStructType {
6876 const type_struct_anon = extraDataTrail(extra, TypeStructAnon, extra_index);
6877 const fields_len = type_struct_anon.data.fields_len;
6878 return .{
6879 .types = .{
6880 .tid = tid,
6881 .start = type_struct_anon.end,
6882 .len = fields_len,
6883 },
6884 .values = .{
6885 .tid = tid,
6886 .start = type_struct_anon.end + fields_len,
6887 .len = fields_len,
6888 },
6889 .names = .{
6890 .tid = tid,
6891 .start = 0,
6892 .len = 0,
6893 },
6894 };6803 };
6895}6804}
68966805
...@@ -7361,7 +7270,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7361,7 +7270,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7361 },7270 },
73627271
7363 .struct_type => unreachable, // use getStructType() instead7272 .struct_type => unreachable, // use getStructType() instead
7364 .anon_struct_type => unreachable, // use getAnonStructType() instead7273 .tuple_type => unreachable, // use getTupleType() instead
7365 .union_type => unreachable, // use getUnionType() instead7274 .union_type => unreachable, // use getUnionType() instead
7366 .opaque_type => unreachable, // use getOpaqueType() instead7275 .opaque_type => unreachable, // use getOpaqueType() instead
73677276
...@@ -7469,9 +7378,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7469,9 +7378,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7469 .field => {7378 .field => {
7470 assert(base_ptr_type.flags.size == .One);7379 assert(base_ptr_type.flags.size == .One);
7471 switch (ip.indexToKey(base_ptr_type.child)) {7380 switch (ip.indexToKey(base_ptr_type.child)) {
7472 .anon_struct_type => |anon_struct_type| {7381 .tuple_type => |tuple_type| {
7473 assert(ptr.base_addr == .field);7382 assert(ptr.base_addr == .field);
7474 assert(base_index.index < anon_struct_type.types.len);7383 assert(base_index.index < tuple_type.types.len);
7475 },7384 },
7476 .struct_type => {7385 .struct_type => {
7477 assert(ptr.base_addr == .field);7386 assert(ptr.base_addr == .field);
...@@ -7808,12 +7717,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7808,12 +7717,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7808 const child = switch (ty_key) {7717 const child = switch (ty_key) {
7809 .array_type => |array_type| array_type.child,7718 .array_type => |array_type| array_type.child,
7810 .vector_type => |vector_type| vector_type.child,7719 .vector_type => |vector_type| vector_type.child,
7811 .anon_struct_type, .struct_type => .none,7720 .tuple_type, .struct_type => .none,
7812 else => unreachable,7721 else => unreachable,
7813 };7722 };
7814 const sentinel = switch (ty_key) {7723 const sentinel = switch (ty_key) {
7815 .array_type => |array_type| array_type.sentinel,7724 .array_type => |array_type| array_type.sentinel,
7816 .vector_type, .anon_struct_type, .struct_type => .none,7725 .vector_type, .tuple_type, .struct_type => .none,
7817 else => unreachable,7726 else => unreachable,
7818 };7727 };
7819 const len_including_sentinel = len + @intFromBool(sentinel != .none);7728 const len_including_sentinel = len + @intFromBool(sentinel != .none);
...@@ -7845,8 +7754,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7845,8 +7754,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7845 assert(ip.typeOf(elem) == field_ty);7754 assert(ip.typeOf(elem) == field_ty);
7846 }7755 }
7847 },7756 },
7848 .anon_struct_type => |anon_struct_type| {7757 .tuple_type => |tuple_type| {
7849 for (aggregate.storage.values(), anon_struct_type.types.get(ip)) |elem, ty| {7758 for (aggregate.storage.values(), tuple_type.types.get(ip)) |elem, ty| {
7850 assert(ip.typeOf(elem) == ty);7759 assert(ip.typeOf(elem) == ty);
7851 }7760 }
7852 },7761 },
...@@ -7862,9 +7771,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7862,9 +7771,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7862 }7771 }
78637772
7864 switch (ty_key) {7773 switch (ty_key) {
7865 .anon_struct_type => |anon_struct_type| opv: {7774 .tuple_type => |tuple_type| opv: {
7866 switch (aggregate.storage) {7775 switch (aggregate.storage) {
7867 .bytes => |bytes| for (anon_struct_type.values.get(ip), bytes.at(0, ip)..) |value, byte| {7776 .bytes => |bytes| for (tuple_type.values.get(ip), bytes.at(0, ip)..) |value, byte| {
7868 if (value == .none) break :opv;7777 if (value == .none) break :opv;
7869 switch (ip.indexToKey(value)) {7778 switch (ip.indexToKey(value)) {
7870 .undef => break :opv,7779 .undef => break :opv,
...@@ -7877,10 +7786,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All...@@ -7877,10 +7786,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
7877 },7786 },
7878 .elems => |elems| if (!std.mem.eql(7787 .elems => |elems| if (!std.mem.eql(
7879 Index,7788 Index,
7880 anon_struct_type.values.get(ip),7789 tuple_type.values.get(ip),
7881 elems,7790 elems,
7882 )) break :opv,7791 )) break :opv,
7883 .repeated_elem => |elem| for (anon_struct_type.values.get(ip)) |value| {7792 .repeated_elem => |elem| for (tuple_type.values.get(ip)) |value| {
7884 if (value != elem) break :opv;7793 if (value != elem) break :opv;
7885 },7794 },
7886 }7795 }
...@@ -8244,7 +8153,6 @@ pub const StructTypeInit = struct {...@@ -8244,7 +8153,6 @@ pub const StructTypeInit = struct {
8244 fields_len: u32,8153 fields_len: u32,
8245 known_non_opv: bool,8154 known_non_opv: bool,
8246 requires_comptime: RequiresComptime,8155 requires_comptime: RequiresComptime,
8247 is_tuple: bool,
8248 any_comptime_fields: bool,8156 any_comptime_fields: bool,
8249 any_default_inits: bool,8157 any_default_inits: bool,
8250 inits_resolved: bool,8158 inits_resolved: bool,
...@@ -8404,7 +8312,6 @@ pub fn getStructType(...@@ -8404,7 +8312,6 @@ pub fn getStructType(
8404 .is_extern = is_extern,8312 .is_extern = is_extern,
8405 .known_non_opv = ini.known_non_opv,8313 .known_non_opv = ini.known_non_opv,
8406 .requires_comptime = ini.requires_comptime,8314 .requires_comptime = ini.requires_comptime,
8407 .is_tuple = ini.is_tuple,
8408 .assumed_runtime_bits = false,8315 .assumed_runtime_bits = false,
8409 .assumed_pointer_aligned = false,8316 .assumed_pointer_aligned = false,
8410 .any_comptime_fields = ini.any_comptime_fields,8317 .any_comptime_fields = ini.any_comptime_fields,
...@@ -8442,10 +8349,8 @@ pub fn getStructType(...@@ -8442,10 +8349,8 @@ pub fn getStructType(
8442 },8349 },
8443 }8350 }
8444 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);8351 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);
8445 if (!ini.is_tuple) {8352 extra.appendAssumeCapacity(.{@intFromEnum(names_map)});
8446 extra.appendAssumeCapacity(.{@intFromEnum(names_map)});8353 extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len);
8447 extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len);
8448 }
8449 if (ini.any_default_inits) {8354 if (ini.any_default_inits) {
8450 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);8355 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);
8451 }8356 }
...@@ -8468,19 +8373,17 @@ pub fn getStructType(...@@ -8468,19 +8373,17 @@ pub fn getStructType(
8468 } };8373 } };
8469}8374}
84708375
8471pub const AnonStructTypeInit = struct {8376pub const TupleTypeInit = struct {
8472 types: []const Index,8377 types: []const Index,
8473 /// This may be empty, indicating this is a tuple.
8474 names: []const NullTerminatedString,
8475 /// These elements may be `none`, indicating runtime-known.8378 /// These elements may be `none`, indicating runtime-known.
8476 values: []const Index,8379 values: []const Index,
8477};8380};
84788381
8479pub fn getAnonStructType(8382pub fn getTupleType(
8480 ip: *InternPool,8383 ip: *InternPool,
8481 gpa: Allocator,8384 gpa: Allocator,
8482 tid: Zcu.PerThread.Id,8385 tid: Zcu.PerThread.Id,
8483 ini: AnonStructTypeInit,8386 ini: TupleTypeInit,
8484) Allocator.Error!Index {8387) Allocator.Error!Index {
8485 assert(ini.types.len == ini.values.len);8388 assert(ini.types.len == ini.values.len);
8486 for (ini.types) |elem| assert(elem != .none);8389 for (ini.types) |elem| assert(elem != .none);
...@@ -8494,23 +8397,17 @@ pub fn getAnonStructType(...@@ -8494,23 +8397,17 @@ pub fn getAnonStructType(
84948397
8495 try items.ensureUnusedCapacity(1);8398 try items.ensureUnusedCapacity(1);
8496 try extra.ensureUnusedCapacity(8399 try extra.ensureUnusedCapacity(
8497 @typeInfo(TypeStructAnon).@"struct".fields.len + (fields_len * 3),8400 @typeInfo(TypeTuple).@"struct".fields.len + (fields_len * 3),
8498 );8401 );
84998402
8500 const extra_index = addExtraAssumeCapacity(extra, TypeStructAnon{8403 const extra_index = addExtraAssumeCapacity(extra, TypeTuple{
8501 .fields_len = fields_len,8404 .fields_len = fields_len,
8502 });8405 });
8503 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.types)});8406 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.types)});
8504 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)});8407 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)});
8505 errdefer extra.mutate.len = prev_extra_len;8408 errdefer extra.mutate.len = prev_extra_len;
85068409
8507 var gop = try ip.getOrPutKey(gpa, tid, .{8410 var gop = try ip.getOrPutKey(gpa, tid, .{ .tuple_type = extraTypeTuple(tid, extra.list.*, extra_index) });
8508 .anon_struct_type = if (ini.names.len == 0) extraTypeTupleAnon(tid, extra.list.*, extra_index) else k: {
8509 assert(ini.names.len == ini.types.len);
8510 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.names)});
8511 break :k extraTypeStructAnon(tid, extra.list.*, extra_index);
8512 },
8513 });
8514 defer gop.deinit();8411 defer gop.deinit();
8515 if (gop == .existing) {8412 if (gop == .existing) {
8516 extra.mutate.len = prev_extra_len;8413 extra.mutate.len = prev_extra_len;
...@@ -8518,7 +8415,7 @@ pub fn getAnonStructType(...@@ -8518,7 +8415,7 @@ pub fn getAnonStructType(
8518 }8415 }
85198416
8520 items.appendAssumeCapacity(.{8417 items.appendAssumeCapacity(.{
8521 .tag = if (ini.names.len == 0) .type_tuple_anon else .type_struct_anon,8418 .tag = .type_tuple,
8522 .data = extra_index,8419 .data = extra_index,
8523 });8420 });
8524 return gop.put();8421 return gop.put();
...@@ -10181,12 +10078,12 @@ pub fn getCoerced(...@@ -10181,12 +10078,12 @@ pub fn getCoerced(
10181 direct: {10078 direct: {
10182 const old_ty_child = switch (ip.indexToKey(old_ty)) {10079 const old_ty_child = switch (ip.indexToKey(old_ty)) {
10183 inline .array_type, .vector_type => |seq_type| seq_type.child,10080 inline .array_type, .vector_type => |seq_type| seq_type.child,
10184 .anon_struct_type, .struct_type => break :direct,10081 .tuple_type, .struct_type => break :direct,
10185 else => unreachable,10082 else => unreachable,
10186 };10083 };
10187 const new_ty_child = switch (ip.indexToKey(new_ty)) {10084 const new_ty_child = switch (ip.indexToKey(new_ty)) {
10188 inline .array_type, .vector_type => |seq_type| seq_type.child,10085 inline .array_type, .vector_type => |seq_type| seq_type.child,
10189 .anon_struct_type, .struct_type => break :direct,10086 .tuple_type, .struct_type => break :direct,
10190 else => unreachable,10087 else => unreachable,
10191 };10088 };
10192 if (old_ty_child != new_ty_child) break :direct;10089 if (old_ty_child != new_ty_child) break :direct;
...@@ -10235,7 +10132,7 @@ pub fn getCoerced(...@@ -10235,7 +10132,7 @@ pub fn getCoerced(
10235 for (agg_elems, 0..) |*elem, i| {10132 for (agg_elems, 0..) |*elem, i| {
10236 const new_elem_ty = switch (ip.indexToKey(new_ty)) {10133 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
10237 inline .array_type, .vector_type => |seq_type| seq_type.child,10134 inline .array_type, .vector_type => |seq_type| seq_type.child,
10238 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[i],10135 .tuple_type => |tuple_type| tuple_type.types.get(ip)[i],
10239 .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i],10136 .struct_type => ip.loadStructType(new_ty).field_types.get(ip)[i],
10240 else => unreachable,10137 else => unreachable,
10241 };10138 };
...@@ -10425,7 +10322,7 @@ pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool {...@@ -10425,7 +10322,7 @@ pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool {
1042510322
10426pub fn isAggregateType(ip: *const InternPool, ty: Index) bool {10323pub fn isAggregateType(ip: *const InternPool, ty: Index) bool {
10427 return switch (ip.indexToKey(ty)) {10324 return switch (ip.indexToKey(ty)) {
10428 .array_type, .vector_type, .anon_struct_type, .struct_type => true,10325 .array_type, .vector_type, .tuple_type, .struct_type => true,
10429 else => false,10326 else => false,
10430 };10327 };
10431}10328}
...@@ -10549,7 +10446,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -10549,7 +10446,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
10549 break :b @sizeOf(u32) * ints;10446 break :b @sizeOf(u32) * ints;
10550 },10447 },
10551 .type_struct => b: {10448 .type_struct => b: {
10552 if (data == 0) break :b 0;
10553 const extra = extraDataTrail(extra_list, Tag.TypeStruct, data);10449 const extra = extraDataTrail(extra_list, Tag.TypeStruct, data);
10554 const info = extra.data;10450 const info = extra.data;
10555 var ints: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len;10451 var ints: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len;
...@@ -10558,10 +10454,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -10558,10 +10454,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
10558 ints += 1 + captures_len;10454 ints += 1 + captures_len;
10559 }10455 }
10560 ints += info.fields_len; // types10456 ints += info.fields_len; // types
10561 if (!info.flags.is_tuple) {10457 ints += 1; // names_map
10562 ints += 1; // names_map10458 ints += info.fields_len; // names
10563 ints += info.fields_len; // names
10564 }
10565 if (info.flags.any_default_inits)10459 if (info.flags.any_default_inits)
10566 ints += info.fields_len; // inits10460 ints += info.fields_len; // inits
10567 if (info.flags.any_aligned_fields)10461 if (info.flags.any_aligned_fields)
...@@ -10573,10 +10467,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -10573,10 +10467,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
10573 ints += info.fields_len; // offsets10467 ints += info.fields_len; // offsets
10574 break :b @sizeOf(u32) * ints;10468 break :b @sizeOf(u32) * ints;
10575 },10469 },
10576 .type_struct_anon => b: {
10577 const info = extraData(extra_list, TypeStructAnon, data);
10578 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
10579 },
10580 .type_struct_packed => b: {10470 .type_struct_packed => b: {
10581 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data);10471 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data);
10582 const captures_len = if (extra.data.flags.any_captures)10472 const captures_len = if (extra.data.flags.any_captures)
...@@ -10597,9 +10487,9 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -10597,9 +10487,9 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
10597 @intFromBool(extra.data.flags.any_captures) + captures_len +10487 @intFromBool(extra.data.flags.any_captures) + captures_len +
10598 extra.data.fields_len * 3);10488 extra.data.fields_len * 3);
10599 },10489 },
10600 .type_tuple_anon => b: {10490 .type_tuple => b: {
10601 const info = extraData(extra_list, TypeStructAnon, data);10491 const info = extraData(extra_list, TypeTuple, data);
10602 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 2 * info.fields_len);10492 break :b @sizeOf(TypeTuple) + (@sizeOf(u32) * 2 * info.fields_len);
10603 },10493 },
1060410494
10605 .type_union => b: {10495 .type_union => b: {
...@@ -10760,10 +10650,9 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -10760,10 +10650,9 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
10760 .type_enum_auto,10650 .type_enum_auto,
10761 .type_opaque,10651 .type_opaque,
10762 .type_struct,10652 .type_struct,
10763 .type_struct_anon,
10764 .type_struct_packed,10653 .type_struct_packed,
10765 .type_struct_packed_inits,10654 .type_struct_packed_inits,
10766 .type_tuple_anon,10655 .type_tuple,
10767 .type_union,10656 .type_union,
10768 .type_function,10657 .type_function,
10769 .undef,10658 .undef,
...@@ -11396,7 +11285,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -11396,7 +11285,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
11396 .anyerror_void_error_union_type,11285 .anyerror_void_error_union_type,
11397 .adhoc_inferred_error_set_type,11286 .adhoc_inferred_error_set_type,
11398 .generic_poison_type,11287 .generic_poison_type,
11399 .empty_struct_type,11288 .empty_tuple_type,
11400 => .type_type,11289 => .type_type,
1140111290
11402 .undef => .undefined_type,11291 .undef => .undefined_type,
...@@ -11407,7 +11296,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -11407,7 +11296,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
11407 .unreachable_value => .noreturn_type,11296 .unreachable_value => .noreturn_type,
11408 .null_value => .null_type,11297 .null_value => .null_type,
11409 .bool_true, .bool_false => .bool_type,11298 .bool_true, .bool_false => .bool_type,
11410 .empty_struct => .empty_struct_type,11299 .empty_tuple => .empty_tuple_type,
11411 .generic_poison => .generic_poison_type,11300 .generic_poison => .generic_poison_type,
1141211301
11413 // This optimization on tags is needed so that indexToKey can call11302 // This optimization on tags is needed so that indexToKey can call
...@@ -11436,10 +11325,9 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -11436,10 +11325,9 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
11436 .type_enum_nonexhaustive,11325 .type_enum_nonexhaustive,
11437 .type_opaque,11326 .type_opaque,
11438 .type_struct,11327 .type_struct,
11439 .type_struct_anon,
11440 .type_struct_packed,11328 .type_struct_packed,
11441 .type_struct_packed_inits,11329 .type_struct_packed_inits,
11442 .type_tuple_anon,11330 .type_tuple,
11443 .type_union,11331 .type_union,
11444 .type_function,11332 .type_function,
11445 => .type_type,11333 => .type_type,
...@@ -11533,7 +11421,7 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {...@@ -11533,7 +11421,7 @@ pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
11533pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {11421pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
11534 return switch (ip.indexToKey(ty)) {11422 return switch (ip.indexToKey(ty)) {
11535 .struct_type => ip.loadStructType(ty).field_types.len,11423 .struct_type => ip.loadStructType(ty).field_types.len,
11536 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,11424 .tuple_type => |tuple_type| tuple_type.types.len,
11537 .array_type => |array_type| array_type.len,11425 .array_type => |array_type| array_type.len,
11538 .vector_type => |vector_type| vector_type.len,11426 .vector_type => |vector_type| vector_type.len,
11539 else => unreachable,11427 else => unreachable,
...@@ -11543,7 +11431,7 @@ pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {...@@ -11543,7 +11431,7 @@ pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
11543pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {11431pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
11544 return switch (ip.indexToKey(ty)) {11432 return switch (ip.indexToKey(ty)) {
11545 .struct_type => ip.loadStructType(ty).field_types.len,11433 .struct_type => ip.loadStructType(ty).field_types.len,
11546 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,11434 .tuple_type => |tuple_type| tuple_type.types.len,
11547 .array_type => |array_type| array_type.lenIncludingSentinel(),11435 .array_type => |array_type| array_type.lenIncludingSentinel(),
11548 .vector_type => |vector_type| vector_type.len,11436 .vector_type => |vector_type| vector_type.len,
11549 else => unreachable,11437 else => unreachable,
...@@ -11708,7 +11596,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -11708,7 +11596,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
1170811596
11709 .optional_noreturn_type => .optional,11597 .optional_noreturn_type => .optional,
11710 .anyerror_void_error_union_type => .error_union,11598 .anyerror_void_error_union_type => .error_union,
11711 .empty_struct_type => .@"struct",11599 .empty_tuple_type => .@"struct",
1171211600
11713 .generic_poison_type => return error.GenericPoison,11601 .generic_poison_type => return error.GenericPoison,
1171411602
...@@ -11727,7 +11615,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -11727,7 +11615,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
11727 .null_value => unreachable,11615 .null_value => unreachable,
11728 .bool_true => unreachable,11616 .bool_true => unreachable,
11729 .bool_false => unreachable,11617 .bool_false => unreachable,
11730 .empty_struct => unreachable,11618 .empty_tuple => unreachable,
11731 .generic_poison => unreachable,11619 .generic_poison => unreachable,
1173211620
11733 _ => switch (index.unwrap(ip).getTag(ip)) {11621 _ => switch (index.unwrap(ip).getTag(ip)) {
...@@ -11768,10 +11656,9 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -11768,10 +11656,9 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
11768 .type_opaque => .@"opaque",11656 .type_opaque => .@"opaque",
1176911657
11770 .type_struct,11658 .type_struct,
11771 .type_struct_anon,
11772 .type_struct_packed,11659 .type_struct_packed,
11773 .type_struct_packed_inits,11660 .type_struct_packed_inits,
11774 .type_tuple_anon,11661 .type_tuple,
11775 => .@"struct",11662 => .@"struct",
1177611663
11777 .type_union => .@"union",11664 .type_union => .@"union",
...@@ -12013,14 +11900,6 @@ pub fn unwrapCoercedFunc(ip: *const InternPool, index: Index) Index {...@@ -12013,14 +11900,6 @@ pub fn unwrapCoercedFunc(ip: *const InternPool, index: Index) Index {
12013 };11900 };
12014}11901}
1201511902
12016pub fn anonStructFieldTypes(ip: *const InternPool, i: Index) []const Index {
12017 return ip.indexToKey(i).anon_struct_type.types;
12018}
12019
12020pub fn anonStructFieldsLen(ip: *const InternPool, i: Index) u32 {
12021 return @intCast(ip.indexToKey(i).anon_struct_type.types.len);
12022}
12023
12024/// Returns the already-existing field with the same name, if any.11903/// Returns the already-existing field with the same name, if any.
12025pub fn addFieldName(11904pub fn addFieldName(
12026 ip: *InternPool,11905 ip: *InternPool,
src/Sema.zig+384-424
...@@ -844,6 +844,7 @@ pub const Block = struct {...@@ -844,6 +844,7 @@ pub const Block = struct {
844844
845 fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index {845 fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index {
846 const pt = block.sema.pt;846 const pt = block.sema.pt;
847 block.sema.code.assertTrackable(inst);
847 return pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{848 return pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{
848 .file = block.getFileScopeIndex(pt.zcu),849 .file = block.getFileScopeIndex(pt.zcu),
849 .inst = inst,850 .inst = inst,
...@@ -1277,6 +1278,7 @@ fn analyzeBodyInner(...@@ -1277,6 +1278,7 @@ fn analyzeBodyInner(
1277 .enum_decl => try sema.zirEnumDecl( block, extended, inst),1278 .enum_decl => try sema.zirEnumDecl( block, extended, inst),
1278 .union_decl => try sema.zirUnionDecl( block, extended, inst),1279 .union_decl => try sema.zirUnionDecl( block, extended, inst),
1279 .opaque_decl => try sema.zirOpaqueDecl( block, extended, inst),1280 .opaque_decl => try sema.zirOpaqueDecl( block, extended, inst),
1281 .tuple_decl => try sema.zirTupleDecl( block, extended),
1280 .this => try sema.zirThis( block, extended),1282 .this => try sema.zirThis( block, extended),
1281 .ret_addr => try sema.zirRetAddr( block, extended),1283 .ret_addr => try sema.zirRetAddr( block, extended),
1282 .builtin_src => try sema.zirBuiltinSrc( block, extended),1284 .builtin_src => try sema.zirBuiltinSrc( block, extended),
...@@ -2338,7 +2340,7 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS...@@ -2338,7 +2340,7 @@ fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazyS
23382340
2339 const struct_type = zcu.typeToStruct(container_ty) orelse break :msg msg;2341 const struct_type = zcu.typeToStruct(container_ty) orelse break :msg msg;
2340 try sema.errNote(.{2342 try sema.errNote(.{
2341 .base_node_inst = struct_type.zir_index.unwrap().?,2343 .base_node_inst = struct_type.zir_index,
2342 .offset = .{ .container_field_value = @intCast(field_index) },2344 .offset = .{ .container_field_value = @intCast(field_index) },
2343 }, msg, "default value set here", .{});2345 }, msg, "default value set here", .{});
2344 break :msg msg;2346 break :msg msg;
...@@ -2651,6 +2653,94 @@ fn analyzeValueAsCallconv(...@@ -2651,6 +2653,94 @@ fn analyzeValueAsCallconv(
2651 };2653 };
2652}2654}
26532655
2656fn zirTupleDecl(
2657 sema: *Sema,
2658 block: *Block,
2659 extended: Zir.Inst.Extended.InstData,
2660) CompileError!Air.Inst.Ref {
2661 const gpa = sema.gpa;
2662 const pt = sema.pt;
2663 const zcu = pt.zcu;
2664 const fields_len = extended.small;
2665 const extra = sema.code.extraData(Zir.Inst.TupleDecl, extended.operand);
2666 var extra_index = extra.end;
2667
2668 const types = try sema.arena.alloc(InternPool.Index, fields_len);
2669 const inits = try sema.arena.alloc(InternPool.Index, fields_len);
2670
2671 const extra_as_refs: []const Zir.Inst.Ref = @ptrCast(sema.code.extra);
2672
2673 for (types, inits, 0..) |*field_ty, *field_init, field_index| {
2674 const zir_field_ty, const zir_field_init = extra_as_refs[extra_index..][0..2].*;
2675 extra_index += 2;
2676
2677 const type_src = block.src(.{ .tuple_field_type = .{
2678 .tuple_decl_node_offset = extra.data.src_node,
2679 .elem_index = @intCast(field_index),
2680 } });
2681 const init_src = block.src(.{ .tuple_field_init = .{
2682 .tuple_decl_node_offset = extra.data.src_node,
2683 .elem_index = @intCast(field_index),
2684 } });
2685
2686 const uncoerced_field_ty = try sema.resolveInst(zir_field_ty);
2687 const field_type = try sema.analyzeAsType(block, type_src, uncoerced_field_ty);
2688 try sema.validateTupleFieldType(block, field_type, type_src);
2689
2690 field_ty.* = field_type.toIntern();
2691 field_init.* = init: {
2692 if (zir_field_init != .none) {
2693 const uncoerced_field_init = try sema.resolveInst(zir_field_init);
2694 const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src);
2695 const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{
2696 .needed_comptime_reason = "tuple field default value must be comptime-known",
2697 });
2698 if (field_init_val.canMutateComptimeVarState(zcu)) {
2699 return sema.fail(block, init_src, "field default value contains reference to comptime-mutable memory", .{});
2700 }
2701 break :init field_init_val.toIntern();
2702 }
2703 if (try sema.typeHasOnePossibleValue(field_type)) |opv| {
2704 break :init opv.toIntern();
2705 }
2706 break :init .none;
2707 };
2708 }
2709
2710 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{
2711 .types = types,
2712 .values = inits,
2713 }));
2714}
2715
2716fn validateTupleFieldType(
2717 sema: *Sema,
2718 block: *Block,
2719 field_ty: Type,
2720 field_ty_src: LazySrcLoc,
2721) CompileError!void {
2722 const gpa = sema.gpa;
2723 const zcu = sema.pt.zcu;
2724 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
2725 return sema.failWithOwnedErrorMsg(block, msg: {
2726 const msg = try sema.errMsg(field_ty_src, "opaque types have unknown size and therefore cannot be directly embedded in tuples", .{});
2727 errdefer msg.destroy(gpa);
2728
2729 try sema.addDeclaredHereNote(msg, field_ty);
2730 break :msg msg;
2731 });
2732 }
2733 if (field_ty.zigTypeTag(zcu) == .noreturn) {
2734 return sema.failWithOwnedErrorMsg(block, msg: {
2735 const msg = try sema.errMsg(field_ty_src, "tuple fields cannot be 'noreturn'", .{});
2736 errdefer msg.destroy(gpa);
2737
2738 try sema.addDeclaredHereNote(msg, field_ty);
2739 break :msg msg;
2740 });
2741 }
2742}
2743
2654/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,2744/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
2655/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.2745/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.
2656fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {2746fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {
...@@ -2774,7 +2864,6 @@ fn zirStructDecl(...@@ -2774,7 +2864,6 @@ fn zirStructDecl(
2774 .fields_len = fields_len,2864 .fields_len = fields_len,
2775 .known_non_opv = small.known_non_opv,2865 .known_non_opv = small.known_non_opv,
2776 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,2866 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
2777 .is_tuple = small.is_tuple,
2778 .any_comptime_fields = small.any_comptime_fields,2867 .any_comptime_fields = small.any_comptime_fields,
2779 .any_default_inits = small.any_default_inits,2868 .any_default_inits = small.any_default_inits,
2780 .inits_resolved = false,2869 .inits_resolved = false,
...@@ -4912,7 +5001,7 @@ fn validateStructInit(...@@ -4912,7 +5001,7 @@ fn validateStructInit(
4912 const default_field_ptr = if (struct_ty.isTuple(zcu))5001 const default_field_ptr = if (struct_ty.isTuple(zcu))
4913 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true)5002 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true)
4914 else5003 else
4915 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), field_src, struct_ty, true);5004 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), struct_ty);
4916 const init = Air.internedToRef(default_val.toIntern());5005 const init = Air.internedToRef(default_val.toIntern());
4917 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);5006 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
4918 }5007 }
...@@ -5104,7 +5193,7 @@ fn validateStructInit(...@@ -5104,7 +5193,7 @@ fn validateStructInit(
5104 const default_field_ptr = if (struct_ty.isTuple(zcu))5193 const default_field_ptr = if (struct_ty.isTuple(zcu))
5105 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true)5194 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true)
5106 else5195 else
5107 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), field_src, struct_ty, true);5196 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), struct_ty);
5108 try sema.checkKnownAllocPtr(block, struct_ptr, default_field_ptr);5197 try sema.checkKnownAllocPtr(block, struct_ptr, default_field_ptr);
5109 const init = Air.internedToRef(field_values[i]);5198 const init = Air.internedToRef(field_values[i]);
5110 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);5199 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
...@@ -8430,22 +8519,6 @@ fn instantiateGenericCall(...@@ -8430,22 +8519,6 @@ fn instantiateGenericCall(
8430 return result;8519 return result;
8431}8520}
84328521
8433fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
8434 const pt = sema.pt;
8435 const zcu = pt.zcu;
8436 const ip = &zcu.intern_pool;
8437 const tuple = switch (ip.indexToKey(ty.toIntern())) {
8438 .anon_struct_type => |tuple| tuple,
8439 else => return,
8440 };
8441 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| {
8442 try sema.resolveTupleLazyValues(block, src, Type.fromInterned(field_ty));
8443 if (field_val == .none) continue;
8444 // TODO: mutate in intern pool
8445 _ = try sema.resolveLazyValue(Value.fromInterned(field_val));
8446 }
8447}
8448
8449fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {8522fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8450 const int_type = sema.code.instructions.items(.data)[@intFromEnum(inst)].int_type;8523 const int_type = sema.code.instructions.items(.data)[@intFromEnum(inst)].int_type;
8451 const ty = try sema.pt.intType(int_type.signedness, int_type.bit_count);8524 const ty = try sema.pt.intType(int_type.signedness, int_type.bit_count);
...@@ -14321,13 +14394,9 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14321,13 +14394,9 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14321 },14394 },
14322 else => {},14395 else => {},
14323 },14396 },
14324 .anon_struct_type => |anon_struct| {14397 .tuple_type => |tuple| {
14325 if (anon_struct.names.len != 0) {14398 const field_index = field_name.toUnsigned(ip) orelse break :hf false;
14326 break :hf mem.indexOfScalar(InternPool.NullTerminatedString, anon_struct.names.get(ip), field_name) != null;14399 break :hf field_index < tuple.types.len;
14327 } else {
14328 const field_index = field_name.toUnsigned(ip) orelse break :hf false;
14329 break :hf field_index < ty.structFieldCount(zcu);
14330 }
14331 },14400 },
14332 .struct_type => {14401 .struct_type => {
14333 break :hf ip.loadStructType(ty.toIntern()).nameIndex(ip, field_name) != null;14402 break :hf ip.loadStructType(ty.toIntern()).nameIndex(ip, field_name) != null;
...@@ -14882,7 +14951,7 @@ fn analyzeTupleCat(...@@ -14882,7 +14951,7 @@ fn analyzeTupleCat(
14882 const dest_fields = lhs_len + rhs_len;14951 const dest_fields = lhs_len + rhs_len;
1488314952
14884 if (dest_fields == 0) {14953 if (dest_fields == 0) {
14885 return Air.internedToRef(Value.empty_struct.toIntern());14954 return .empty_tuple;
14886 }14955 }
14887 if (lhs_len == 0) {14956 if (lhs_len == 0) {
14888 return rhs;14957 return rhs;
...@@ -14928,10 +14997,9 @@ fn analyzeTupleCat(...@@ -14928,10 +14997,9 @@ fn analyzeTupleCat(
14928 break :rs runtime_src;14997 break :rs runtime_src;
14929 };14998 };
1493014999
14931 const tuple_ty = try zcu.intern_pool.getAnonStructType(zcu.gpa, pt.tid, .{15000 const tuple_ty = try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{
14932 .types = types,15001 .types = types,
14933 .values = values,15002 .values = values,
14934 .names = &.{},
14935 });15003 });
1493615004
14937 const runtime_src = opt_runtime_src orelse {15005 const runtime_src = opt_runtime_src orelse {
...@@ -15263,7 +15331,7 @@ fn analyzeTupleMul(...@@ -15263,7 +15331,7 @@ fn analyzeTupleMul(
15263 return sema.fail(block, len_src, "operation results in overflow", .{});15331 return sema.fail(block, len_src, "operation results in overflow", .{});
1526415332
15265 if (final_len == 0) {15333 if (final_len == 0) {
15266 return Air.internedToRef(Value.empty_struct.toIntern());15334 return .empty_tuple;
15267 }15335 }
15268 const types = try sema.arena.alloc(InternPool.Index, final_len);15336 const types = try sema.arena.alloc(InternPool.Index, final_len);
15269 const values = try sema.arena.alloc(InternPool.Index, final_len);15337 const values = try sema.arena.alloc(InternPool.Index, final_len);
...@@ -15289,10 +15357,9 @@ fn analyzeTupleMul(...@@ -15289,10 +15357,9 @@ fn analyzeTupleMul(
15289 break :rs runtime_src;15357 break :rs runtime_src;
15290 };15358 };
1529115359
15292 const tuple_ty = try zcu.intern_pool.getAnonStructType(zcu.gpa, pt.tid, .{15360 const tuple_ty = try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{
15293 .types = types,15361 .types = types,
15294 .values = values,15362 .values = values,
15295 .names = &.{},
15296 });15363 });
1529715364
15298 const runtime_src = opt_runtime_src orelse {15365 const runtime_src = opt_runtime_src orelse {
...@@ -16689,7 +16756,7 @@ fn zirOverflowArithmetic(...@@ -16689,7 +16756,7 @@ fn zirOverflowArithmetic(
16689 const maybe_rhs_val = try sema.resolveValue(rhs);16756 const maybe_rhs_val = try sema.resolveValue(rhs);
1669016757
16691 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);16758 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
16692 const overflow_ty = Type.fromInterned(ip.indexToKey(tuple_ty.toIntern()).anon_struct_type.types.get(ip)[1]);16759 const overflow_ty = Type.fromInterned(ip.indexToKey(tuple_ty.toIntern()).tuple_type.types.get(ip)[1]);
1669316760
16694 var result: struct {16761 var result: struct {
16695 inst: Air.Inst.Ref = .none,16762 inst: Air.Inst.Ref = .none,
...@@ -16873,10 +16940,9 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {...@@ -16873,10 +16940,9 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
1687316940
16874 const types = [2]InternPool.Index{ ty.toIntern(), ov_ty.toIntern() };16941 const types = [2]InternPool.Index{ ty.toIntern(), ov_ty.toIntern() };
16875 const values = [2]InternPool.Index{ .none, .none };16942 const values = [2]InternPool.Index{ .none, .none };
16876 const tuple_ty = try ip.getAnonStructType(zcu.gpa, pt.tid, .{16943 const tuple_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{
16877 .types = &types,16944 .types = &types,
16878 .values = &values,16945 .values = &values,
16879 .names = &.{},
16880 });16946 });
16881 return Type.fromInterned(tuple_ty);16947 return Type.fromInterned(tuple_ty);
16882}16948}
...@@ -18908,16 +18974,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18908,16 +18974,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18908 defer gpa.free(struct_field_vals);18974 defer gpa.free(struct_field_vals);
18909 fv: {18975 fv: {
18910 const struct_type = switch (ip.indexToKey(ty.toIntern())) {18976 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
18911 .anon_struct_type => |anon_struct_type| {18977 .tuple_type => |tuple_type| {
18912 struct_field_vals = try gpa.alloc(InternPool.Index, anon_struct_type.types.len);18978 struct_field_vals = try gpa.alloc(InternPool.Index, tuple_type.types.len);
18913 for (struct_field_vals, 0..) |*struct_field_val, field_index| {18979 for (struct_field_vals, 0..) |*struct_field_val, field_index| {
18914 const field_ty = anon_struct_type.types.get(ip)[field_index];18980 const field_ty = tuple_type.types.get(ip)[field_index];
18915 const field_val = anon_struct_type.values.get(ip)[field_index];18981 const field_val = tuple_type.values.get(ip)[field_index];
18916 const name_val = v: {18982 const name_val = v: {
18917 const field_name = if (anon_struct_type.names.len != 0)18983 const field_name = try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
18918 anon_struct_type.names.get(ip)[field_index]
18919 else
18920 try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
18921 const field_name_len = field_name.length(ip);18984 const field_name_len = field_name.length(ip);
18922 const new_decl_ty = try pt.arrayType(.{18985 const new_decl_ty = try pt.arrayType(.{
18923 .len = field_name_len,18986 .len = field_name_len,
...@@ -20509,8 +20572,8 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is...@@ -20509,8 +20572,8 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
20509 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;20572 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
20510 const src = block.nodeOffset(inst_data.src_node);20573 const src = block.nodeOffset(inst_data.src_node);
20511 const ty_operand = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {20574 const ty_operand = sema.resolveType(block, src, inst_data.operand) catch |err| switch (err) {
20512 // Generic poison means this is an untyped anonymous empty struct init20575 // Generic poison means this is an untyped anonymous empty struct/array init
20513 error.GenericPoison => return .empty_struct,20576 error.GenericPoison => return .empty_tuple,
20514 else => |e| return e,20577 else => |e| return e,
20515 };20578 };
20516 const init_ty = if (is_byref) ty: {20579 const init_ty = if (is_byref) ty: {
...@@ -20671,7 +20734,7 @@ fn zirStructInit(...@@ -20671,7 +20734,7 @@ fn zirStructInit(
20671 const result_ty = sema.resolveType(block, src, first_field_type_extra.container_type) catch |err| switch (err) {20734 const result_ty = sema.resolveType(block, src, first_field_type_extra.container_type) catch |err| switch (err) {
20672 error.GenericPoison => {20735 error.GenericPoison => {
20673 // The type wasn't actually known, so treat this as an anon struct init.20736 // The type wasn't actually known, so treat this as an anon struct init.
20674 return sema.structInitAnon(block, src, .typed_init, extra.data, extra.end, is_ref);20737 return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref);
20675 },20738 },
20676 else => |e| return e,20739 else => |e| return e,
20677 };20740 };
...@@ -20837,39 +20900,28 @@ fn finishStructInit(...@@ -20837,39 +20900,28 @@ fn finishStructInit(
20837 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);20900 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
2083820901
20839 switch (ip.indexToKey(struct_ty.toIntern())) {20902 switch (ip.indexToKey(struct_ty.toIntern())) {
20840 .anon_struct_type => |anon_struct| {20903 .tuple_type => |tuple| {
20841 // We can't get the slices, as the coercion may invalidate them.20904 // We can't get the slices, as the coercion may invalidate them.
20842 for (0..anon_struct.types.len) |i| {20905 for (0..tuple.types.len) |i| {
20843 if (field_inits[i] != .none) {20906 if (field_inits[i] != .none) {
20844 // Coerce the init value to the field type.20907 // Coerce the init value to the field type.
20845 const field_src = block.src(.{ .init_elem = .{20908 const field_src = block.src(.{ .init_elem = .{
20846 .init_node_offset = init_src.offset.node_offset.x,20909 .init_node_offset = init_src.offset.node_offset.x,
20847 .elem_index = @intCast(i),20910 .elem_index = @intCast(i),
20848 } });20911 } });
20849 const field_ty = Type.fromInterned(anon_struct.types.get(ip)[i]);20912 const field_ty = Type.fromInterned(tuple.types.get(ip)[i]);
20850 field_inits[i] = try sema.coerce(block, field_ty, field_inits[i], field_src);20913 field_inits[i] = try sema.coerce(block, field_ty, field_inits[i], field_src);
20851 continue;20914 continue;
20852 }20915 }
2085320916
20854 const default_val = anon_struct.values.get(ip)[i];20917 const default_val = tuple.values.get(ip)[i];
2085520918
20856 if (default_val == .none) {20919 if (default_val == .none) {
20857 if (anon_struct.names.len == 0) {20920 const template = "missing tuple field with index {d}";
20858 const template = "missing tuple field with index {d}";20921 if (root_msg) |msg| {
20859 if (root_msg) |msg| {20922 try sema.errNote(init_src, msg, template, .{i});
20860 try sema.errNote(init_src, msg, template, .{i});
20861 } else {
20862 root_msg = try sema.errMsg(init_src, template, .{i});
20863 }
20864 } else {20923 } else {
20865 const field_name = anon_struct.names.get(ip)[i];20924 root_msg = try sema.errMsg(init_src, template, .{i});
20866 const template = "missing struct field: {}";
20867 const args = .{field_name.fmt(ip)};
20868 if (root_msg) |msg| {
20869 try sema.errNote(init_src, msg, template, args);
20870 } else {
20871 root_msg = try sema.errMsg(init_src, template, args);
20872 }
20873 }20925 }
20874 } else {20926 } else {
20875 field_inits[i] = Air.internedToRef(default_val);20927 field_inits[i] = Air.internedToRef(default_val);
...@@ -20894,22 +20946,13 @@ fn finishStructInit(...@@ -20894,22 +20946,13 @@ fn finishStructInit(
2089420946
20895 const field_init = struct_type.fieldInit(ip, i);20947 const field_init = struct_type.fieldInit(ip, i);
20896 if (field_init == .none) {20948 if (field_init == .none) {
20897 if (!struct_type.isTuple(ip)) {20949 const field_name = struct_type.field_names.get(ip)[i];
20898 const field_name = struct_type.field_names.get(ip)[i];20950 const template = "missing struct field: {}";
20899 const template = "missing struct field: {}";20951 const args = .{field_name.fmt(ip)};
20900 const args = .{field_name.fmt(ip)};20952 if (root_msg) |msg| {
20901 if (root_msg) |msg| {20953 try sema.errNote(init_src, msg, template, args);
20902 try sema.errNote(init_src, msg, template, args);
20903 } else {
20904 root_msg = try sema.errMsg(init_src, template, args);
20905 }
20906 } else {20954 } else {
20907 const template = "missing tuple field with index {d}";20955 root_msg = try sema.errMsg(init_src, template, args);
20908 if (root_msg) |msg| {
20909 try sema.errNote(init_src, msg, template, .{i});
20910 } else {
20911 root_msg = try sema.errMsg(init_src, template, .{i});
20912 }
20913 }20956 }
20914 } else {20957 } else {
20915 field_inits[i] = Air.internedToRef(field_init);20958 field_inits[i] = Air.internedToRef(field_init);
...@@ -20970,8 +21013,7 @@ fn finishStructInit(...@@ -20970,8 +21013,7 @@ fn finishStructInit(
20970 const base_ptr = try sema.optEuBasePtrInit(block, alloc, init_src);21013 const base_ptr = try sema.optEuBasePtrInit(block, alloc, init_src);
20971 for (field_inits, 0..) |field_init, i_usize| {21014 for (field_inits, 0..) |field_init, i_usize| {
20972 const i: u32 = @intCast(i_usize);21015 const i: u32 = @intCast(i_usize);
20973 const field_src = dest_src;21016 const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, base_ptr, i, struct_ty);
20974 const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, base_ptr, i, field_src, struct_ty, true);
20975 try sema.storePtr(block, dest_src, field_ptr, field_init);21017 try sema.storePtr(block, dest_src, field_ptr, field_init);
20976 }21018 }
2097721019
...@@ -20995,13 +21037,14 @@ fn zirStructInitAnon(...@@ -20995,13 +21037,14 @@ fn zirStructInitAnon(
20995 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;21037 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
20996 const src = block.nodeOffset(inst_data.src_node);21038 const src = block.nodeOffset(inst_data.src_node);
20997 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);21039 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
20998 return sema.structInitAnon(block, src, .anon_init, extra.data, extra.end, false);21040 return sema.structInitAnon(block, src, inst, .anon_init, extra.data, extra.end, false);
20999}21041}
2100021042
21001fn structInitAnon(21043fn structInitAnon(
21002 sema: *Sema,21044 sema: *Sema,
21003 block: *Block,21045 block: *Block,
21004 src: LazySrcLoc,21046 src: LazySrcLoc,
21047 inst: Zir.Inst.Index,
21005 /// It is possible for a typed struct_init to be downgraded to an anonymous init due to a21048 /// It is possible for a typed struct_init to be downgraded to an anonymous init due to a
21006 /// generic poison type. In this case, we need to know to interpret the extra data differently.21049 /// generic poison type. In this case, we need to know to interpret the extra data differently.
21007 comptime kind: enum { anon_init, typed_init },21050 comptime kind: enum { anon_init, typed_init },
...@@ -21022,6 +21065,8 @@ fn structInitAnon(...@@ -21022,6 +21065,8 @@ fn structInitAnon(
21022 const values = try sema.arena.alloc(InternPool.Index, types.len);21065 const values = try sema.arena.alloc(InternPool.Index, types.len);
21023 const names = try sema.arena.alloc(InternPool.NullTerminatedString, types.len);21066 const names = try sema.arena.alloc(InternPool.NullTerminatedString, types.len);
2102421067
21068 var any_values = false;
21069
21025 // Find which field forces the expression to be runtime, if any.21070 // Find which field forces the expression to be runtime, if any.
21026 const opt_runtime_index = rs: {21071 const opt_runtime_index = rs: {
21027 var runtime_index: ?usize = null;21072 var runtime_index: ?usize = null;
...@@ -21063,6 +21108,7 @@ fn structInitAnon(...@@ -21063,6 +21108,7 @@ fn structInitAnon(
21063 }21108 }
21064 if (try sema.resolveValue(init)) |init_val| {21109 if (try sema.resolveValue(init)) |init_val| {
21065 field_val.* = init_val.toIntern();21110 field_val.* = init_val.toIntern();
21111 any_values = true;
21066 } else {21112 } else {
21067 field_val.* = .none;21113 field_val.* = .none;
21068 runtime_index = @intCast(i_usize);21114 runtime_index = @intCast(i_usize);
...@@ -21071,18 +21117,76 @@ fn structInitAnon(...@@ -21071,18 +21117,76 @@ fn structInitAnon(
21071 break :rs runtime_index;21117 break :rs runtime_index;
21072 };21118 };
2107321119
21074 const tuple_ty = try ip.getAnonStructType(gpa, pt.tid, .{21120 // We treat anonymous struct types as reified types, because there are similarities:
21075 .names = names,21121 // * They use a form of structural equivalence, which we can easily model using a custom hash
21076 .types = types,21122 // * They do not have captures
21077 .values = values,21123 // * They immediately have their fields resolved
21078 });21124 // In general, other code should treat anon struct types and reified struct types identically,
21125 // so there's no point having a separate `InternPool.NamespaceType` field for them.
21126 const type_hash: u64 = hash: {
21127 var hasher = std.hash.Wyhash.init(0);
21128 hasher.update(std.mem.sliceAsBytes(types));
21129 hasher.update(std.mem.sliceAsBytes(values));
21130 hasher.update(std.mem.sliceAsBytes(names));
21131 break :hash hasher.final();
21132 };
21133 const tracked_inst = try block.trackZir(inst);
21134 const struct_ty = switch (try ip.getStructType(gpa, pt.tid, .{
21135 .layout = .auto,
21136 .fields_len = extra_data.fields_len,
21137 .known_non_opv = false,
21138 .requires_comptime = .unknown,
21139 .any_comptime_fields = any_values,
21140 .any_default_inits = any_values,
21141 .inits_resolved = true,
21142 .any_aligned_fields = false,
21143 .key = .{ .reified = .{
21144 .zir_index = tracked_inst,
21145 .type_hash = type_hash,
21146 } },
21147 }, false)) {
21148 .wip => |wip| ty: {
21149 errdefer wip.cancel(ip, pt.tid);
21150 wip.setName(ip, try sema.createTypeName(block, .anon, "struct", inst, wip.index));
21151
21152 const struct_type = ip.loadStructType(wip.index);
21153
21154 for (names, values, 0..) |name, init_val, field_idx| {
21155 assert(struct_type.addFieldName(ip, name) == null);
21156 if (init_val != .none) struct_type.setFieldComptime(ip, field_idx);
21157 }
21158
21159 @memcpy(struct_type.field_types.get(ip), types);
21160 if (any_values) {
21161 @memcpy(struct_type.field_inits.get(ip), values);
21162 }
21163
21164 const new_namespace_index = try pt.createNamespace(.{
21165 .parent = block.namespace.toOptional(),
21166 .owner_type = wip.index,
21167 .file_scope = block.getFileScopeIndex(zcu),
21168 .generation = zcu.generation,
21169 });
21170 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip.index);
21171 try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });
21172 codegen_type: {
21173 if (zcu.comp.config.use_llvm) break :codegen_type;
21174 if (block.ownerModule().strip) break :codegen_type;
21175 try zcu.comp.queueJob(.{ .codegen_type = wip.index });
21176 }
21177 break :ty wip.finish(ip, new_cau_index.toOptional(), new_namespace_index);
21178 },
21179 .existing => |ty| ty,
21180 };
21181 try sema.declareDependency(.{ .interned = struct_ty });
21182 try sema.addTypeReferenceEntry(src, struct_ty);
2107921183
21080 const runtime_index = opt_runtime_index orelse {21184 const runtime_index = opt_runtime_index orelse {
21081 const tuple_val = try pt.intern(.{ .aggregate = .{21185 const struct_val = try pt.intern(.{ .aggregate = .{
21082 .ty = tuple_ty,21186 .ty = struct_ty,
21083 .storage = .{ .elems = values },21187 .storage = .{ .elems = values },
21084 } });21188 } });
21085 return sema.addConstantMaybeRef(tuple_val, is_ref);21189 return sema.addConstantMaybeRef(struct_val, is_ref);
21086 };21190 };
2108721191
21088 try sema.requireRuntimeBlock(block, LazySrcLoc.unneeded, block.src(.{ .init_elem = .{21192 try sema.requireRuntimeBlock(block, LazySrcLoc.unneeded, block.src(.{ .init_elem = .{
...@@ -21093,7 +21197,7 @@ fn structInitAnon(...@@ -21093,7 +21197,7 @@ fn structInitAnon(
21093 if (is_ref) {21197 if (is_ref) {
21094 const target = zcu.getTarget();21198 const target = zcu.getTarget();
21095 const alloc_ty = try pt.ptrTypeSema(.{21199 const alloc_ty = try pt.ptrTypeSema(.{
21096 .child = tuple_ty,21200 .child = struct_ty,
21097 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },21201 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
21098 });21202 });
21099 const alloc = try block.addTy(.alloc, alloc_ty);21203 const alloc = try block.addTy(.alloc, alloc_ty);
...@@ -21131,7 +21235,7 @@ fn structInitAnon(...@@ -21131,7 +21235,7 @@ fn structInitAnon(
21131 element_refs[i] = try sema.resolveInst(item.data.init);21235 element_refs[i] = try sema.resolveInst(item.data.init);
21132 }21236 }
2113321237
21134 return block.addAggregateInit(Type.fromInterned(tuple_ty), element_refs);21238 return block.addAggregateInit(Type.fromInterned(struct_ty), element_refs);
21135}21239}
2113621240
21137fn zirArrayInit(21241fn zirArrayInit(
...@@ -21340,10 +21444,9 @@ fn arrayInitAnon(...@@ -21340,10 +21444,9 @@ fn arrayInitAnon(
21340 break :rs runtime_src;21444 break :rs runtime_src;
21341 };21445 };
2134221446
21343 const tuple_ty = try ip.getAnonStructType(gpa, pt.tid, .{21447 const tuple_ty = try ip.getTupleType(gpa, pt.tid, .{
21344 .types = types,21448 .types = types,
21345 .values = values,21449 .values = values,
21346 .names = &.{},
21347 });21450 });
2134821451
21349 const runtime_src = opt_runtime_src orelse {21452 const runtime_src = opt_runtime_src orelse {
...@@ -21440,12 +21543,9 @@ fn fieldType(...@@ -21440,12 +21543,9 @@ fn fieldType(
21440 try cur_ty.resolveFields(pt);21543 try cur_ty.resolveFields(pt);
21441 switch (cur_ty.zigTypeTag(zcu)) {21544 switch (cur_ty.zigTypeTag(zcu)) {
21442 .@"struct" => switch (ip.indexToKey(cur_ty.toIntern())) {21545 .@"struct" => switch (ip.indexToKey(cur_ty.toIntern())) {
21443 .anon_struct_type => |anon_struct| {21546 .tuple_type => |tuple| {
21444 const field_index = if (anon_struct.names.len == 0)21547 const field_index = try sema.tupleFieldIndex(block, cur_ty, field_name, field_src);
21445 try sema.tupleFieldIndex(block, cur_ty, field_name, field_src)21548 return Air.internedToRef(tuple.types.get(ip)[field_index]);
21446 else
21447 try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
21448 return Air.internedToRef(anon_struct.types.get(ip)[field_index]);
21449 },21549 },
21450 .struct_type => {21550 .struct_type => {
21451 const struct_type = ip.loadStructType(cur_ty.toIntern());21551 const struct_type = ip.loadStructType(cur_ty.toIntern());
...@@ -22095,7 +22195,16 @@ fn zirReify(...@@ -22095,7 +22195,16 @@ fn zirReify(
22095 .needed_comptime_reason = "struct fields must be comptime-known",22195 .needed_comptime_reason = "struct fields must be comptime-known",
22096 });22196 });
2209722197
22098 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy, is_tuple_val.toBool());22198 if (is_tuple_val.toBool()) {
22199 switch (layout) {
22200 .@"extern" => return sema.fail(block, src, "extern tuples are not supported", .{}),
22201 .@"packed" => return sema.fail(block, src, "packed tuples are not supported", .{}),
22202 .auto => {},
22203 }
22204 return sema.reifyTuple(block, src, fields_arr);
22205 } else {
22206 return sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy);
22207 }
22099 },22208 },
22100 .@"enum" => {22209 .@"enum" => {
22101 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));22210 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
...@@ -22696,6 +22805,104 @@ fn reifyUnion(...@@ -22696,6 +22805,104 @@ fn reifyUnion(
22696 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));22805 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));
22697}22806}
2269822807
22808fn reifyTuple(
22809 sema: *Sema,
22810 block: *Block,
22811 src: LazySrcLoc,
22812 fields_val: Value,
22813) CompileError!Air.Inst.Ref {
22814 const pt = sema.pt;
22815 const zcu = pt.zcu;
22816 const gpa = sema.gpa;
22817 const ip = &zcu.intern_pool;
22818
22819 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));
22820
22821 const types = try sema.arena.alloc(InternPool.Index, fields_len);
22822 const inits = try sema.arena.alloc(InternPool.Index, fields_len);
22823
22824 for (types, inits, 0..) |*field_ty, *field_init, field_idx| {
22825 const field_info = try fields_val.elemValue(pt, field_idx);
22826
22827 const field_name_val = try field_info.fieldValue(pt, 0);
22828 const field_type_val = try field_info.fieldValue(pt, 1);
22829 const field_default_value_val = try field_info.fieldValue(pt, 2);
22830 const field_is_comptime_val = try field_info.fieldValue(pt, 3);
22831 const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4));
22832
22833 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{
22834 .needed_comptime_reason = "tuple field name must be comptime-known",
22835 });
22836 const field_type = field_type_val.toType();
22837 const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: {
22838 const ptr_ty = try pt.singleConstPtrType(field_type_val.toType());
22839 // We need to do this deref here, so we won't check for this error case later on.
22840 const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime(
22841 block,
22842 src,
22843 .{ .needed_comptime_reason = "tuple field default value must be comptime-known" },
22844 );
22845 // Resolve the value so that lazy values do not create distinct types.
22846 break :d (try sema.resolveLazyValue(val)).toIntern();
22847 } else .none;
22848
22849 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(
22850 block,
22851 src,
22852 "tuple cannot have non-numeric field '{}'",
22853 .{field_name.fmt(ip)},
22854 );
22855 if (field_name_index != field_idx) {
22856 return sema.fail(
22857 block,
22858 src,
22859 "tuple field name '{}' does not match field index {}",
22860 .{ field_name_index, field_idx },
22861 );
22862 }
22863
22864 try sema.validateTupleFieldType(block, field_type, src);
22865
22866 {
22867 const alignment_ok = ok: {
22868 if (field_alignment_val.toIntern() == .zero) break :ok true;
22869 const given_align = try field_alignment_val.getUnsignedIntSema(pt) orelse break :ok false;
22870 const abi_align = (try field_type.abiAlignmentSema(pt)).toByteUnits() orelse 0;
22871 break :ok abi_align == given_align;
22872 };
22873 if (!alignment_ok) {
22874 return sema.fail(block, src, "tuple fields cannot specify alignment", .{});
22875 }
22876 }
22877
22878 if (field_is_comptime_val.toBool() and field_default_value == .none) {
22879 return sema.fail(block, src, "comptime field without default initialization value", .{});
22880 }
22881
22882 if (!field_is_comptime_val.toBool() and field_default_value != .none) {
22883 return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{});
22884 }
22885
22886 const default_or_opv: InternPool.Index = default: {
22887 if (field_default_value != .none) {
22888 break :default field_default_value;
22889 }
22890 if (try sema.typeHasOnePossibleValue(field_type)) |opv| {
22891 break :default opv.toIntern();
22892 }
22893 break :default .none;
22894 };
22895
22896 field_ty.* = field_type.toIntern();
22897 field_init.* = default_or_opv;
22898 }
22899
22900 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{
22901 .types = types,
22902 .values = inits,
22903 }));
22904}
22905
22699fn reifyStruct(22906fn reifyStruct(
22700 sema: *Sema,22907 sema: *Sema,
22701 block: *Block,22908 block: *Block,
...@@ -22705,7 +22912,6 @@ fn reifyStruct(...@@ -22705,7 +22912,6 @@ fn reifyStruct(
22705 opt_backing_int_val: Value,22912 opt_backing_int_val: Value,
22706 fields_val: Value,22913 fields_val: Value,
22707 name_strategy: Zir.Inst.NameStrategy,22914 name_strategy: Zir.Inst.NameStrategy,
22708 is_tuple: bool,
22709) CompileError!Air.Inst.Ref {22915) CompileError!Air.Inst.Ref {
22710 const pt = sema.pt;22916 const pt = sema.pt;
22711 const zcu = pt.zcu;22917 const zcu = pt.zcu;
...@@ -22725,7 +22931,6 @@ fn reifyStruct(...@@ -22725,7 +22931,6 @@ fn reifyStruct(
22725 var hasher = std.hash.Wyhash.init(0);22931 var hasher = std.hash.Wyhash.init(0);
22726 std.hash.autoHash(&hasher, layout);22932 std.hash.autoHash(&hasher, layout);
22727 std.hash.autoHash(&hasher, opt_backing_int_val.toIntern());22933 std.hash.autoHash(&hasher, opt_backing_int_val.toIntern());
22728 std.hash.autoHash(&hasher, is_tuple);
22729 std.hash.autoHash(&hasher, fields_len);22934 std.hash.autoHash(&hasher, fields_len);
2273022935
22731 var any_comptime_fields = false;22936 var any_comptime_fields = false;
...@@ -22781,7 +22986,6 @@ fn reifyStruct(...@@ -22781,7 +22986,6 @@ fn reifyStruct(
22781 .fields_len = fields_len,22986 .fields_len = fields_len,
22782 .known_non_opv = false,22987 .known_non_opv = false,
22783 .requires_comptime = .unknown,22988 .requires_comptime = .unknown,
22784 .is_tuple = is_tuple,
22785 .any_comptime_fields = any_comptime_fields,22989 .any_comptime_fields = any_comptime_fields,
22786 .any_default_inits = any_default_inits,22990 .any_default_inits = any_default_inits,
22787 .any_aligned_fields = any_aligned_fields,22991 .any_aligned_fields = any_aligned_fields,
...@@ -22800,12 +23004,6 @@ fn reifyStruct(...@@ -22800,12 +23004,6 @@ fn reifyStruct(
22800 };23004 };
22801 errdefer wip_ty.cancel(ip, pt.tid);23005 errdefer wip_ty.cancel(ip, pt.tid);
2280223006
22803 if (is_tuple) switch (layout) {
22804 .@"extern" => return sema.fail(block, src, "extern tuples are not supported", .{}),
22805 .@"packed" => return sema.fail(block, src, "packed tuples are not supported", .{}),
22806 .auto => {},
22807 };
22808
22809 wip_ty.setName(ip, try sema.createTypeName(23007 wip_ty.setName(ip, try sema.createTypeName(
22810 block,23008 block,
22811 name_strategy,23009 name_strategy,
...@@ -22828,22 +23026,7 @@ fn reifyStruct(...@@ -22828,22 +23026,7 @@ fn reifyStruct(
22828 const field_ty = field_type_val.toType();23026 const field_ty = field_type_val.toType();
22829 // Don't pass a reason; first loop acts as an assertion that this is valid.23027 // Don't pass a reason; first loop acts as an assertion that this is valid.
22830 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);23028 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
22831 if (is_tuple) {23029 if (struct_type.addFieldName(ip, field_name)) |prev_index| {
22832 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(
22833 block,
22834 src,
22835 "tuple cannot have non-numeric field '{}'",
22836 .{field_name.fmt(ip)},
22837 );
22838 if (field_name_index != field_idx) {
22839 return sema.fail(
22840 block,
22841 src,
22842 "tuple field name '{}' does not match field index {}",
22843 .{ field_name_index, field_idx },
22844 );
22845 }
22846 } else if (struct_type.addFieldName(ip, field_name)) |prev_index| {
22847 _ = prev_index; // TODO: better source location23030 _ = prev_index; // TODO: better source location
22848 return sema.fail(block, src, "duplicate struct field name {}", .{field_name.fmt(ip)});23031 return sema.fail(block, src, "duplicate struct field name {}", .{field_name.fmt(ip)});
22849 }23032 }
...@@ -25579,7 +25762,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -25579,7 +25762,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
25579 const args = try sema.resolveInst(extra.args);25762 const args = try sema.resolveInst(extra.args);
2558025763
25581 const args_ty = sema.typeOf(args);25764 const args_ty = sema.typeOf(args);
25582 if (!args_ty.isTuple(zcu) and args_ty.toIntern() != .empty_struct_type) {25765 if (!args_ty.isTuple(zcu)) {
25583 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(pt)});25766 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(pt)});
25584 }25767 }
2558525768
...@@ -27471,7 +27654,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -27471,7 +27654,7 @@ fn explainWhyTypeIsComptimeInner(
27471 for (0..struct_type.field_types.len) |i| {27654 for (0..struct_type.field_types.len) |i| {
27472 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);27655 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
27473 const field_src: LazySrcLoc = .{27656 const field_src: LazySrcLoc = .{
27474 .base_node_inst = struct_type.zir_index.unwrap().?,27657 .base_node_inst = struct_type.zir_index,
27475 .offset = .{ .container_field_type = @intCast(i) },27658 .offset = .{ .container_field_type = @intCast(i) },
27476 };27659 };
2747727660
...@@ -28236,11 +28419,10 @@ fn fieldVal(...@@ -28236,11 +28419,10 @@ fn fieldVal(
28236 return Air.internedToRef(enum_val.toIntern());28419 return Air.internedToRef(enum_val.toIntern());
28237 },28420 },
28238 .@"struct", .@"opaque" => {28421 .@"struct", .@"opaque" => {
28239 switch (child_type.toIntern()) {28422 if (!child_type.isTuple(zcu) and child_type.toIntern() != .anyopaque_type) {
28240 .empty_struct_type, .anyopaque_type => {}, // no namespace28423 if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| {
28241 else => if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| {
28242 return inst;28424 return inst;
28243 },28425 }
28244 }28426 }
28245 return sema.failWithBadMemberAccess(block, child_type, src, field_name);28427 return sema.failWithBadMemberAccess(block, child_type, src, field_name);
28246 },28428 },
...@@ -28788,9 +28970,6 @@ fn structFieldPtr(...@@ -28788,9 +28970,6 @@ fn structFieldPtr(
28788 }28970 }
28789 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);28971 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
28790 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);28972 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
28791 } else if (struct_ty.isAnonStruct(zcu)) {
28792 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
28793 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
28794 }28973 }
2879528974
28796 const struct_type = zcu.typeToStruct(struct_ty).?;28975 const struct_type = zcu.typeToStruct(struct_ty).?;
...@@ -28798,7 +28977,7 @@ fn structFieldPtr(...@@ -28798,7 +28977,7 @@ fn structFieldPtr(
28798 const field_index = struct_type.nameIndex(ip, field_name) orelse28977 const field_index = struct_type.nameIndex(ip, field_name) orelse
28799 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name);28978 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name);
2880028979
28801 return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, field_name_src, struct_ty, initializing);28980 return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, struct_ty);
28802}28981}
2880328982
28804fn structFieldPtrByIndex(28983fn structFieldPtrByIndex(
...@@ -28807,16 +28986,11 @@ fn structFieldPtrByIndex(...@@ -28807,16 +28986,11 @@ fn structFieldPtrByIndex(
28807 src: LazySrcLoc,28986 src: LazySrcLoc,
28808 struct_ptr: Air.Inst.Ref,28987 struct_ptr: Air.Inst.Ref,
28809 field_index: u32,28988 field_index: u32,
28810 field_src: LazySrcLoc,
28811 struct_ty: Type,28989 struct_ty: Type,
28812 initializing: bool,
28813) CompileError!Air.Inst.Ref {28990) CompileError!Air.Inst.Ref {
28814 const pt = sema.pt;28991 const pt = sema.pt;
28815 const zcu = pt.zcu;28992 const zcu = pt.zcu;
28816 const ip = &zcu.intern_pool;28993 const ip = &zcu.intern_pool;
28817 if (struct_ty.isAnonStruct(zcu)) {
28818 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);
28819 }
2882028994
28821 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {28995 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
28822 const val = try struct_ptr_val.ptrField(field_index, pt);28996 const val = try struct_ptr_val.ptrField(field_index, pt);
...@@ -28909,8 +29083,6 @@ fn structFieldVal(...@@ -28909,8 +29083,6 @@ fn structFieldVal(
28909 switch (ip.indexToKey(struct_ty.toIntern())) {29083 switch (ip.indexToKey(struct_ty.toIntern())) {
28910 .struct_type => {29084 .struct_type => {
28911 const struct_type = ip.loadStructType(struct_ty.toIntern());29085 const struct_type = ip.loadStructType(struct_ty.toIntern());
28912 if (struct_type.isTuple(ip))
28913 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2891429086
28915 const field_index = struct_type.nameIndex(ip, field_name) orelse29087 const field_index = struct_type.nameIndex(ip, field_name) orelse
28916 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name);29088 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name);
...@@ -28935,13 +29107,8 @@ fn structFieldVal(...@@ -28935,13 +29107,8 @@ fn structFieldVal(
28935 try field_ty.resolveLayout(pt);29107 try field_ty.resolveLayout(pt);
28936 return block.addStructFieldVal(struct_byval, field_index, field_ty);29108 return block.addStructFieldVal(struct_byval, field_index, field_ty);
28937 },29109 },
28938 .anon_struct_type => |anon_struct| {29110 .tuple_type => {
28939 if (anon_struct.names.len == 0) {29111 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
28940 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
28941 } else {
28942 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
28943 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
28944 }
28945 },29112 },
28946 else => unreachable,29113 else => unreachable,
28947 }29114 }
...@@ -30087,39 +30254,7 @@ fn coerceExtra(...@@ -30087,39 +30254,7 @@ fn coerceExtra(
30087 },30254 },
30088 else => {},30255 else => {},
30089 },30256 },
30090 .One => switch (Type.fromInterned(dest_info.child).zigTypeTag(zcu)) {30257 .One => {},
30091 .@"union" => {
30092 // pointer to anonymous struct to pointer to union
30093 if (inst_ty.isSinglePointer(zcu) and
30094 inst_ty.childType(zcu).isAnonStruct(zcu) and
30095 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
30096 {
30097 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
30098 }
30099 },
30100 .@"struct" => {
30101 // pointer to anonymous struct to pointer to struct
30102 if (inst_ty.isSinglePointer(zcu) and
30103 inst_ty.childType(zcu).isAnonStruct(zcu) and
30104 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
30105 {
30106 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src) catch |err| switch (err) {
30107 error.NotCoercible => break :pointer,
30108 else => |e| return e,
30109 };
30110 }
30111 },
30112 .array => {
30113 // pointer to tuple to pointer to array
30114 if (inst_ty.isSinglePointer(zcu) and
30115 inst_ty.childType(zcu).isTuple(zcu) and
30116 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
30117 {
30118 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
30119 }
30120 },
30121 else => {},
30122 },
30123 .Slice => to_slice: {30258 .Slice => to_slice: {
30124 if (inst_ty.zigTypeTag(zcu) == .array) {30259 if (inst_ty.zigTypeTag(zcu) == .array) {
30125 return sema.fail(30260 return sema.fail(
...@@ -30368,11 +30503,6 @@ fn coerceExtra(...@@ -30368,11 +30503,6 @@ fn coerceExtra(
30368 },30503 },
30369 .@"union" => switch (inst_ty.zigTypeTag(zcu)) {30504 .@"union" => switch (inst_ty.zigTypeTag(zcu)) {
30370 .@"enum", .enum_literal => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),30505 .@"enum", .enum_literal => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),
30371 .@"struct" => {
30372 if (inst_ty.isAnonStruct(zcu)) {
30373 return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src);
30374 }
30375 },
30376 else => {},30506 else => {},
30377 },30507 },
30378 .array => switch (inst_ty.zigTypeTag(zcu)) {30508 .array => switch (inst_ty.zigTypeTag(zcu)) {
...@@ -30402,9 +30532,6 @@ fn coerceExtra(...@@ -30402,9 +30532,6 @@ fn coerceExtra(
30402 },30532 },
30403 .vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),30533 .vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),
30404 .@"struct" => {30534 .@"struct" => {
30405 if (inst == .empty_struct) {
30406 return sema.arrayInitEmpty(block, inst_src, dest_ty);
30407 }
30408 if (inst_ty.isTuple(zcu)) {30535 if (inst_ty.isTuple(zcu)) {
30409 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);30536 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
30410 }30537 }
...@@ -30421,10 +30548,7 @@ fn coerceExtra(...@@ -30421,10 +30548,7 @@ fn coerceExtra(
30421 else => {},30548 else => {},
30422 },30549 },
30423 .@"struct" => blk: {30550 .@"struct" => blk: {
30424 if (inst == .empty_struct) {30551 if (inst_ty.isTuple(zcu)) {
30425 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);
30426 }
30427 if (inst_ty.isTupleOrAnonStruct(zcu)) {
30428 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {30552 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {
30429 error.NotCoercible => break :blk,30553 error.NotCoercible => break :blk,
30430 else => |e| return e,30554 else => |e| return e,
...@@ -32208,97 +32332,6 @@ fn coerceEnumToUnion(...@@ -32208,97 +32332,6 @@ fn coerceEnumToUnion(
32208 return sema.failWithOwnedErrorMsg(block, msg);32332 return sema.failWithOwnedErrorMsg(block, msg);
32209}32333}
3221032334
32211fn coerceAnonStructToUnion(
32212 sema: *Sema,
32213 block: *Block,
32214 union_ty: Type,
32215 union_ty_src: LazySrcLoc,
32216 inst: Air.Inst.Ref,
32217 inst_src: LazySrcLoc,
32218) !Air.Inst.Ref {
32219 const pt = sema.pt;
32220 const zcu = pt.zcu;
32221 const ip = &zcu.intern_pool;
32222 const inst_ty = sema.typeOf(inst);
32223 const field_info: union(enum) {
32224 name: InternPool.NullTerminatedString,
32225 count: usize,
32226 } = switch (ip.indexToKey(inst_ty.toIntern())) {
32227 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)
32228 .{ .name = anon_struct_type.names.get(ip)[0] }
32229 else
32230 .{ .count = anon_struct_type.names.len },
32231 .struct_type => name: {
32232 const field_names = ip.loadStructType(inst_ty.toIntern()).field_names.get(ip);
32233 break :name if (field_names.len == 1)
32234 .{ .name = field_names[0] }
32235 else
32236 .{ .count = field_names.len };
32237 },
32238 else => unreachable,
32239 };
32240 switch (field_info) {
32241 .name => |field_name| {
32242 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
32243 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
32244 },
32245 .count => |field_count| {
32246 assert(field_count != 1);
32247 const msg = msg: {
32248 const msg = if (field_count > 1) try sema.errMsg(
32249 inst_src,
32250 "cannot initialize multiple union fields at once; unions can only have one active field",
32251 .{},
32252 ) else try sema.errMsg(
32253 inst_src,
32254 "union initializer must initialize one field",
32255 .{},
32256 );
32257 errdefer msg.destroy(sema.gpa);
32258
32259 // TODO add notes for where the anon struct was created to point out
32260 // the extra fields.
32261
32262 try sema.addDeclaredHereNote(msg, union_ty);
32263 break :msg msg;
32264 };
32265 return sema.failWithOwnedErrorMsg(block, msg);
32266 },
32267 }
32268}
32269
32270fn coerceAnonStructToUnionPtrs(
32271 sema: *Sema,
32272 block: *Block,
32273 ptr_union_ty: Type,
32274 union_ty_src: LazySrcLoc,
32275 ptr_anon_struct: Air.Inst.Ref,
32276 anon_struct_src: LazySrcLoc,
32277) !Air.Inst.Ref {
32278 const pt = sema.pt;
32279 const zcu = pt.zcu;
32280 const union_ty = ptr_union_ty.childType(zcu);
32281 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);
32282 const union_inst = try sema.coerceAnonStructToUnion(block, union_ty, union_ty_src, anon_struct, anon_struct_src);
32283 return sema.analyzeRef(block, union_ty_src, union_inst);
32284}
32285
32286fn coerceAnonStructToStructPtrs(
32287 sema: *Sema,
32288 block: *Block,
32289 ptr_struct_ty: Type,
32290 struct_ty_src: LazySrcLoc,
32291 ptr_anon_struct: Air.Inst.Ref,
32292 anon_struct_src: LazySrcLoc,
32293) !Air.Inst.Ref {
32294 const pt = sema.pt;
32295 const zcu = pt.zcu;
32296 const struct_ty = ptr_struct_ty.childType(zcu);
32297 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);
32298 const struct_inst = try sema.coerceTupleToStruct(block, struct_ty, anon_struct, anon_struct_src);
32299 return sema.analyzeRef(block, struct_ty_src, struct_inst);
32300}
32301
32302/// If the lengths match, coerces element-wise.32335/// If the lengths match, coerces element-wise.
32303fn coerceArrayLike(32336fn coerceArrayLike(
32304 sema: *Sema,32337 sema: *Sema,
...@@ -32530,7 +32563,7 @@ fn coerceTupleToStruct(...@@ -32530,7 +32563,7 @@ fn coerceTupleToStruct(
32530 try struct_ty.resolveFields(pt);32563 try struct_ty.resolveFields(pt);
32531 try struct_ty.resolveStructFieldInits(pt);32564 try struct_ty.resolveStructFieldInits(pt);
3253232565
32533 if (struct_ty.isTupleOrAnonStruct(zcu)) {32566 if (struct_ty.isTuple(zcu)) {
32534 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);32567 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
32535 }32568 }
3253632569
...@@ -32542,7 +32575,7 @@ fn coerceTupleToStruct(...@@ -32542,7 +32575,7 @@ fn coerceTupleToStruct(
32542 const inst_ty = sema.typeOf(inst);32575 const inst_ty = sema.typeOf(inst);
32543 var runtime_src: ?LazySrcLoc = null;32576 var runtime_src: ?LazySrcLoc = null;
32544 const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {32577 const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
32545 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,32578 .tuple_type => |tuple| tuple.types.len,
32546 .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len,32579 .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len,
32547 else => unreachable,32580 else => unreachable,
32548 };32581 };
...@@ -32557,7 +32590,7 @@ fn coerceTupleToStruct(...@@ -32557,7 +32590,7 @@ fn coerceTupleToStruct(
32557 const coerced = try sema.coerce(block, struct_field_ty, elem_ref, field_src);32590 const coerced = try sema.coerce(block, struct_field_ty, elem_ref, field_src);
32558 field_refs[struct_field_index] = coerced;32591 field_refs[struct_field_index] = coerced;
32559 if (struct_type.fieldIsComptime(ip, struct_field_index)) {32592 if (struct_type.fieldIsComptime(ip, struct_field_index)) {
32560 const init_val = (try sema.resolveValue(coerced)) orelse {32593 const init_val = try sema.resolveValue(coerced) orelse {
32561 return sema.failWithNeededComptime(block, field_src, .{32594 return sema.failWithNeededComptime(block, field_src, .{
32562 .needed_comptime_reason = "value stored in comptime field must be comptime-known",32595 .needed_comptime_reason = "value stored in comptime field must be comptime-known",
32563 });32596 });
...@@ -32636,8 +32669,7 @@ fn coerceTupleToTuple(...@@ -32636,8 +32669,7 @@ fn coerceTupleToTuple(
32636 const zcu = pt.zcu;32669 const zcu = pt.zcu;
32637 const ip = &zcu.intern_pool;32670 const ip = &zcu.intern_pool;
32638 const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) {32671 const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) {
32639 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,32672 .tuple_type => |tuple_type| tuple_type.types.len,
32640 .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.len,
32641 else => unreachable,32673 else => unreachable,
32642 };32674 };
32643 const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);32675 const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);
...@@ -32646,8 +32678,7 @@ fn coerceTupleToTuple(...@@ -32646,8 +32678,7 @@ fn coerceTupleToTuple(
3264632678
32647 const inst_ty = sema.typeOf(inst);32679 const inst_ty = sema.typeOf(inst);
32648 const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) {32680 const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
32649 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,32681 .tuple_type => |tuple_type| tuple_type.types.len,
32650 .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len,
32651 else => unreachable,32682 else => unreachable,
32652 };32683 };
32653 if (src_field_count > dest_field_count) return error.NotCoercible;32684 if (src_field_count > dest_field_count) return error.NotCoercible;
...@@ -32656,24 +32687,19 @@ fn coerceTupleToTuple(...@@ -32656,24 +32687,19 @@ fn coerceTupleToTuple(
32656 for (0..dest_field_count) |field_index_usize| {32687 for (0..dest_field_count) |field_index_usize| {
32657 const field_i: u32 = @intCast(field_index_usize);32688 const field_i: u32 = @intCast(field_index_usize);
32658 const field_src = inst_src; // TODO better source location32689 const field_src = inst_src; // TODO better source location
32659 const field_name = inst_ty.structFieldName(field_index_usize, zcu).unwrap() orelse
32660 try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_index_usize}, .no_embedded_nulls);
32661
32662 if (field_name.eqlSlice("len", ip))
32663 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
3266432690
32665 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {32691 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {
32666 .anon_struct_type => |anon_struct_type| anon_struct_type.types.get(ip)[field_index_usize],32692 .tuple_type => |tuple_type| tuple_type.types.get(ip)[field_index_usize],
32667 .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.get(ip)[field_index_usize],32693 .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.get(ip)[field_index_usize],
32668 else => unreachable,32694 else => unreachable,
32669 };32695 };
32670 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {32696 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
32671 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize],32697 .tuple_type => |tuple_type| tuple_type.values.get(ip)[field_index_usize],
32672 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, field_index_usize),32698 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, field_index_usize),
32673 else => unreachable,32699 else => unreachable,
32674 };32700 };
3267532701
32676 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);32702 const field_index: u32 = @intCast(field_index_usize);
3267732703
32678 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);32704 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
32679 const coerced = try sema.coerce(block, Type.fromInterned(field_ty), elem_ref, field_src);32705 const coerced = try sema.coerce(block, Type.fromInterned(field_ty), elem_ref, field_src);
...@@ -32707,28 +32733,18 @@ fn coerceTupleToTuple(...@@ -32707,28 +32733,18 @@ fn coerceTupleToTuple(
32707 if (field_ref.* != .none) continue;32733 if (field_ref.* != .none) continue;
3270832734
32709 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {32735 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
32710 .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i],32736 .tuple_type => |tuple_type| tuple_type.values.get(ip)[i],
32711 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, i),32737 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, i),
32712 else => unreachable,32738 else => unreachable,
32713 };32739 };
3271432740
32715 const field_src = inst_src; // TODO better source location32741 const field_src = inst_src; // TODO better source location
32716 if (default_val == .none) {32742 if (default_val == .none) {
32717 const field_name = tuple_ty.structFieldName(i, zcu).unwrap() orelse {32743 const template = "missing tuple field: {d}";
32718 const template = "missing tuple field: {d}";
32719 if (root_msg) |msg| {
32720 try sema.errNote(field_src, msg, template, .{i});
32721 } else {
32722 root_msg = try sema.errMsg(field_src, template, .{i});
32723 }
32724 continue;
32725 };
32726 const template = "missing struct field: {}";
32727 const args = .{field_name.fmt(ip)};
32728 if (root_msg) |msg| {32744 if (root_msg) |msg| {
32729 try sema.errNote(field_src, msg, template, args);32745 try sema.errNote(field_src, msg, template, .{i});
32730 } else {32746 } else {
32731 root_msg = try sema.errMsg(field_src, template, args);32747 root_msg = try sema.errMsg(field_src, template, .{i});
32732 }32748 }
32733 continue;32749 continue;
32734 }32750 }
...@@ -34265,8 +34281,8 @@ const PeerResolveStrategy = enum {...@@ -34265,8 +34281,8 @@ const PeerResolveStrategy = enum {
34265 fixed_int,34281 fixed_int,
34266 /// The type must be some fixed-width float type.34282 /// The type must be some fixed-width float type.
34267 fixed_float,34283 fixed_float,
34268 /// The type must be a struct literal or tuple type.34284 /// The type must be a tuple.
34269 coercible_struct,34285 tuple,
34270 /// The peers must all be of the same type.34286 /// The peers must all be of the same type.
34271 exact,34287 exact,
3427234288
...@@ -34350,9 +34366,9 @@ const PeerResolveStrategy = enum {...@@ -34350,9 +34366,9 @@ const PeerResolveStrategy = enum {
34350 .fixed_float => .{ .either, .fixed_float },34366 .fixed_float => .{ .either, .fixed_float },
34351 else => .{ .all_s1, s1 }, // doesn't override anything later34367 else => .{ .all_s1, s1 }, // doesn't override anything later
34352 },34368 },
34353 .coercible_struct => switch (s1) {34369 .tuple => switch (s1) {
34354 .exact => .{ .all_s1, .exact },34370 .exact => .{ .all_s1, .exact },
34355 else => .{ .all_s0, .coercible_struct },34371 else => .{ .all_s0, .tuple },
34356 },34372 },
34357 .exact => .{ .all_s0, .exact },34373 .exact => .{ .all_s0, .exact },
34358 };34374 };
...@@ -34393,7 +34409,7 @@ const PeerResolveStrategy = enum {...@@ -34393,7 +34409,7 @@ const PeerResolveStrategy = enum {
34393 .error_set => .error_set,34409 .error_set => .error_set,
34394 .error_union => .error_union,34410 .error_union => .error_union,
34395 .enum_literal, .@"enum", .@"union" => .enum_or_union,34411 .enum_literal, .@"enum", .@"union" => .enum_or_union,
34396 .@"struct" => if (ty.isTupleOrAnonStruct(zcu)) .coercible_struct else .exact,34412 .@"struct" => if (ty.isTuple(zcu)) .tuple else .exact,
34397 .@"fn" => .func,34413 .@"fn" => .func,
34398 };34414 };
34399 }34415 }
...@@ -35501,19 +35517,17 @@ fn resolvePeerTypesInner(...@@ -35501,19 +35517,17 @@ fn resolvePeerTypesInner(
35501 return .{ .success = opt_cur_ty.? };35517 return .{ .success = opt_cur_ty.? };
35502 },35518 },
3550335519
35504 .coercible_struct => {35520 .tuple => {
35505 // First, check that every peer has the same approximate structure (field count and names)35521 // First, check that every peer has the same approximate structure (field count)
3550635522
35507 var opt_first_idx: ?usize = null;35523 var opt_first_idx: ?usize = null;
35508 var is_tuple: bool = undefined;35524 var is_tuple: bool = undefined;
35509 var field_count: usize = undefined;35525 var field_count: usize = undefined;
35510 // Only defined for non-tuples.
35511 var field_names: []InternPool.NullTerminatedString = undefined;
3551235526
35513 for (peer_tys, 0..) |opt_ty, i| {35527 for (peer_tys, 0..) |opt_ty, i| {
35514 const ty = opt_ty orelse continue;35528 const ty = opt_ty orelse continue;
3551535529
35516 if (!ty.isTupleOrAnonStruct(zcu)) {35530 if (!ty.isTuple(zcu)) {
35517 return .{ .conflict = .{35531 return .{ .conflict = .{
35518 .peer_idx_a = strat_reason,35532 .peer_idx_a = strat_reason,
35519 .peer_idx_b = i,35533 .peer_idx_b = i,
...@@ -35524,31 +35538,15 @@ fn resolvePeerTypesInner(...@@ -35524,31 +35538,15 @@ fn resolvePeerTypesInner(
35524 opt_first_idx = i;35538 opt_first_idx = i;
35525 is_tuple = ty.isTuple(zcu);35539 is_tuple = ty.isTuple(zcu);
35526 field_count = ty.structFieldCount(zcu);35540 field_count = ty.structFieldCount(zcu);
35527 if (!is_tuple) {
35528 const names = ip.indexToKey(ty.toIntern()).anon_struct_type.names.get(ip);
35529 field_names = try sema.arena.dupe(InternPool.NullTerminatedString, names);
35530 }
35531 continue;35541 continue;
35532 };35542 };
3553335543
35534 if (ty.isTuple(zcu) != is_tuple or ty.structFieldCount(zcu) != field_count) {35544 if (ty.structFieldCount(zcu) != field_count) {
35535 return .{ .conflict = .{35545 return .{ .conflict = .{
35536 .peer_idx_a = first_idx,35546 .peer_idx_a = first_idx,
35537 .peer_idx_b = i,35547 .peer_idx_b = i,
35538 } };35548 } };
35539 }35549 }
35540
35541 if (!is_tuple) {
35542 for (field_names, 0..) |expected, field_index_usize| {
35543 const field_index: u32 = @intCast(field_index_usize);
35544 const actual = ty.structFieldName(field_index, zcu).unwrap().?;
35545 if (actual == expected) continue;
35546 return .{ .conflict = .{
35547 .peer_idx_a = first_idx,
35548 .peer_idx_b = i,
35549 } };
35550 }
35551 }
35552 }35550 }
3555335551
35554 assert(opt_first_idx != null);35552 assert(opt_first_idx != null);
...@@ -35578,10 +35576,7 @@ fn resolvePeerTypesInner(...@@ -35578,10 +35576,7 @@ fn resolvePeerTypesInner(
35578 else => |result| {35576 else => |result| {
35579 const result_buf = try sema.arena.create(PeerResolveResult);35577 const result_buf = try sema.arena.create(PeerResolveResult);
35580 result_buf.* = result;35578 result_buf.* = result;
35581 const field_name = if (is_tuple)35579 const field_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
35582 try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls)
35583 else
35584 field_names[field_index];
3558535580
35586 // The error info needs the field types, but we can't reuse sub_peer_tys35581 // The error info needs the field types, but we can't reuse sub_peer_tys
35587 // since the recursive call may have clobbered it.35582 // since the recursive call may have clobbered it.
...@@ -35636,9 +35631,8 @@ fn resolvePeerTypesInner(...@@ -35636,9 +35631,8 @@ fn resolvePeerTypesInner(
35636 field_val.* = if (comptime_val) |v| v.toIntern() else .none;35631 field_val.* = if (comptime_val) |v| v.toIntern() else .none;
35637 }35632 }
3563835633
35639 const final_ty = try ip.getAnonStructType(zcu.gpa, pt.tid, .{35634 const final_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{
35640 .types = field_types,35635 .types = field_types,
35641 .names = if (is_tuple) &.{} else field_names,
35642 .values = field_vals,35636 .values = field_vals,
35643 });35637 });
3564435638
...@@ -35778,7 +35772,7 @@ pub fn resolveStructAlignment(...@@ -35778,7 +35772,7 @@ pub fn resolveStructAlignment(
35778 const ip = &zcu.intern_pool;35772 const ip = &zcu.intern_pool;
35779 const target = zcu.getTarget();35773 const target = zcu.getTarget();
3578035774
35781 assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?);35775 assert(sema.owner.unwrap().cau == struct_type.cau);
3578235776
35783 assert(struct_type.layout != .@"packed");35777 assert(struct_type.layout != .@"packed");
35784 assert(struct_type.flagsUnordered(ip).alignment == .none);35778 assert(struct_type.flagsUnordered(ip).alignment == .none);
...@@ -35821,7 +35815,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -35821,7 +35815,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
35821 const ip = &zcu.intern_pool;35815 const ip = &zcu.intern_pool;
35822 const struct_type = zcu.typeToStruct(ty) orelse return;35816 const struct_type = zcu.typeToStruct(ty) orelse return;
3582335817
35824 assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?);35818 assert(sema.owner.unwrap().cau == struct_type.cau);
3582535819
35826 if (struct_type.haveLayout(ip))35820 if (struct_type.haveLayout(ip))
35827 return;35821 return;
...@@ -35921,12 +35915,14 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -35921,12 +35915,14 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
35921 return a_align.compare(.gt, b_align);35915 return a_align.compare(.gt, b_align);
35922 }35916 }
35923 };35917 };
35924 if (struct_type.isTuple(ip) or !zcu.backendSupportsFeature(.field_reordering)) {35918 if (!zcu.backendSupportsFeature(.field_reordering)) {
35925 // TODO: don't handle tuples differently. This logic exists only because it35919 // TODO: we should probably also reorder tuple fields? This is a bit weird because it'll involve
35926 // uncovers latent bugs if removed. Fix the latent bugs and remove this logic!35920 // mutating the `InternPool` for a non-container type.
35927 // Likewise, implement field reordering support in all the backends!35921 //
35922 // TODO: implement field reordering support in all the backends!
35923 //
35928 // This logic does not reorder fields; it only moves the omitted ones to the end35924 // This logic does not reorder fields; it only moves the omitted ones to the end
35929 // so that logic elsewhere does not need to special-case tuples.35925 // so that logic elsewhere does not need to special-case here.
35930 var i: usize = 0;35926 var i: usize = 0;
35931 var off: usize = 0;35927 var off: usize = 0;
35932 while (i + off < runtime_order.len) {35928 while (i + off < runtime_order.len) {
...@@ -35966,7 +35962,7 @@ fn backingIntType(...@@ -35966,7 +35962,7 @@ fn backingIntType(
35966 const gpa = zcu.gpa;35962 const gpa = zcu.gpa;
35967 const ip = &zcu.intern_pool;35963 const ip = &zcu.intern_pool;
3596835964
35969 const cau_index = struct_type.cau.unwrap().?;35965 const cau_index = struct_type.cau;
3597035966
35971 var analysis_arena = std.heap.ArenaAllocator.init(gpa);35967 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
35972 defer analysis_arena.deinit();35968 defer analysis_arena.deinit();
...@@ -35978,7 +35974,7 @@ fn backingIntType(...@@ -35978,7 +35974,7 @@ fn backingIntType(
35978 .instructions = .{},35974 .instructions = .{},
35979 .inlining = null,35975 .inlining = null,
35980 .is_comptime = true,35976 .is_comptime = true,
35981 .src_base_inst = struct_type.zir_index.unwrap().?,35977 .src_base_inst = struct_type.zir_index,
35982 .type_name_ctx = struct_type.name,35978 .type_name_ctx = struct_type.name,
35983 };35979 };
35984 defer assert(block.instructions.items.len == 0);35980 defer assert(block.instructions.items.len == 0);
...@@ -35992,8 +35988,8 @@ fn backingIntType(...@@ -35992,8 +35988,8 @@ fn backingIntType(
35992 break :blk accumulator;35988 break :blk accumulator;
35993 };35989 };
3599435990
35995 const zir = zcu.namespacePtr(struct_type.namespace.unwrap().?).fileScope(zcu).zir;35991 const zir = zcu.namespacePtr(struct_type.namespace).fileScope(zcu).zir;
35996 const zir_index = struct_type.zir_index.unwrap().?.resolve(ip) orelse return error.AnalysisFail;35992 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
35997 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;35993 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
35998 assert(extended.opcode == .struct_decl);35994 assert(extended.opcode == .struct_decl);
35999 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);35995 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
...@@ -36014,7 +36010,7 @@ fn backingIntType(...@@ -36014,7 +36010,7 @@ fn backingIntType(
36014 extra_index += 1;36010 extra_index += 1;
3601536011
36016 const backing_int_src: LazySrcLoc = .{36012 const backing_int_src: LazySrcLoc = .{
36017 .base_node_inst = struct_type.zir_index.unwrap().?,36013 .base_node_inst = struct_type.zir_index,
36018 .offset = .{ .node_offset_container_tag = 0 },36014 .offset = .{ .node_offset_container_tag = 0 },
36019 };36015 };
36020 const backing_int_ty = blk: {36016 const backing_int_ty = blk: {
...@@ -36261,7 +36257,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {...@@ -36261,7 +36257,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
36261 const ip = &zcu.intern_pool;36257 const ip = &zcu.intern_pool;
36262 const struct_type = zcu.typeToStruct(ty).?;36258 const struct_type = zcu.typeToStruct(ty).?;
3626336259
36264 assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?);36260 assert(sema.owner.unwrap().cau == struct_type.cau);
3626536261
36266 if (struct_type.setFullyResolved(ip)) return;36262 if (struct_type.setFullyResolved(ip)) return;
36267 errdefer struct_type.clearFullyResolved(ip);36263 errdefer struct_type.clearFullyResolved(ip);
...@@ -36319,7 +36315,7 @@ pub fn resolveStructFieldTypes(...@@ -36319,7 +36315,7 @@ pub fn resolveStructFieldTypes(
36319 const zcu = pt.zcu;36315 const zcu = pt.zcu;
36320 const ip = &zcu.intern_pool;36316 const ip = &zcu.intern_pool;
3632136317
36322 assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?);36318 assert(sema.owner.unwrap().cau == struct_type.cau);
3632336319
36324 if (struct_type.haveFieldTypes(ip)) return;36320 if (struct_type.haveFieldTypes(ip)) return;
3632536321
...@@ -36345,7 +36341,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -36345,7 +36341,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
36345 const ip = &zcu.intern_pool;36341 const ip = &zcu.intern_pool;
36346 const struct_type = zcu.typeToStruct(ty) orelse return;36342 const struct_type = zcu.typeToStruct(ty) orelse return;
3634736343
36348 assert(sema.owner.unwrap().cau == struct_type.cau.unwrap().?);36344 assert(sema.owner.unwrap().cau == struct_type.cau);
3634936345
36350 // Inits can start as resolved36346 // Inits can start as resolved
36351 if (struct_type.haveFieldInits(ip)) return;36347 if (struct_type.haveFieldInits(ip)) return;
...@@ -36607,12 +36603,12 @@ fn structFields(...@@ -36607,12 +36603,12 @@ fn structFields(
36607 const zcu = pt.zcu;36603 const zcu = pt.zcu;
36608 const gpa = zcu.gpa;36604 const gpa = zcu.gpa;
36609 const ip = &zcu.intern_pool;36605 const ip = &zcu.intern_pool;
36610 const cau_index = struct_type.cau.unwrap().?;36606 const cau_index = struct_type.cau;
36611 const namespace_index = ip.getCau(cau_index).namespace;36607 const namespace_index = ip.getCau(cau_index).namespace;
36612 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;36608 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
36613 const zir_index = struct_type.zir_index.unwrap().?.resolve(ip) orelse return error.AnalysisFail;36609 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
3661436610
36615 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);36611 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);
3661636612
36617 if (fields_len == 0) switch (struct_type.layout) {36613 if (fields_len == 0) switch (struct_type.layout) {
36618 .@"packed" => {36614 .@"packed" => {
...@@ -36632,7 +36628,7 @@ fn structFields(...@@ -36632,7 +36628,7 @@ fn structFields(
36632 .instructions = .{},36628 .instructions = .{},
36633 .inlining = null,36629 .inlining = null,
36634 .is_comptime = true,36630 .is_comptime = true,
36635 .src_base_inst = struct_type.zir_index.unwrap().?,36631 .src_base_inst = struct_type.zir_index,
36636 .type_name_ctx = struct_type.name,36632 .type_name_ctx = struct_type.name,
36637 };36633 };
36638 defer assert(block_scope.instructions.items.len == 0);36634 defer assert(block_scope.instructions.items.len == 0);
...@@ -36673,12 +36669,8 @@ fn structFields(...@@ -36673,12 +36669,8 @@ fn structFields(
3667336669
36674 if (is_comptime) struct_type.setFieldComptime(ip, field_i);36670 if (is_comptime) struct_type.setFieldComptime(ip, field_i);
3667536671
36676 var opt_field_name_zir: ?[:0]const u8 = null;36672 const field_name_zir: [:0]const u8 = zir.nullTerminatedString(@enumFromInt(zir.extra[extra_index]));
36677 if (!small.is_tuple) {36673 extra_index += 2; // field_name, doc_comment
36678 opt_field_name_zir = zir.nullTerminatedString(@enumFromInt(zir.extra[extra_index]));
36679 extra_index += 1;
36680 }
36681 extra_index += 1; // doc_comment
3668236674
36683 fields[field_i] = .{};36675 fields[field_i] = .{};
3668436676
...@@ -36690,10 +36682,8 @@ fn structFields(...@@ -36690,10 +36682,8 @@ fn structFields(
36690 extra_index += 1;36682 extra_index += 1;
3669136683
36692 // This string needs to outlive the ZIR code.36684 // This string needs to outlive the ZIR code.
36693 if (opt_field_name_zir) |field_name_zir| {36685 const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);
36694 const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);36686 assert(struct_type.addFieldName(ip, field_name) == null);
36695 assert(struct_type.addFieldName(ip, field_name) == null);
36696 }
3669736687
36698 if (has_align) {36688 if (has_align) {
36699 fields[field_i].align_body_len = zir.extra[extra_index];36689 fields[field_i].align_body_len = zir.extra[extra_index];
...@@ -36713,7 +36703,7 @@ fn structFields(...@@ -36713,7 +36703,7 @@ fn structFields(
3671336703
36714 for (fields, 0..) |zir_field, field_i| {36704 for (fields, 0..) |zir_field, field_i| {
36715 const ty_src: LazySrcLoc = .{36705 const ty_src: LazySrcLoc = .{
36716 .base_node_inst = struct_type.zir_index.unwrap().?,36706 .base_node_inst = struct_type.zir_index,
36717 .offset = .{ .container_field_type = @intCast(field_i) },36707 .offset = .{ .container_field_type = @intCast(field_i) },
36718 };36708 };
36719 const field_ty: Type = ty: {36709 const field_ty: Type = ty: {
...@@ -36785,7 +36775,7 @@ fn structFields(...@@ -36785,7 +36775,7 @@ fn structFields(
36785 extra_index += body.len;36775 extra_index += body.len;
36786 const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);36776 const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
36787 const align_src: LazySrcLoc = .{36777 const align_src: LazySrcLoc = .{
36788 .base_node_inst = struct_type.zir_index.unwrap().?,36778 .base_node_inst = struct_type.zir_index,
36789 .offset = .{ .container_field_align = @intCast(field_i) },36779 .offset = .{ .container_field_align = @intCast(field_i) },
36790 };36780 };
36791 const field_align = try sema.analyzeAsAlign(&block_scope, align_src, align_ref);36781 const field_align = try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
...@@ -36812,11 +36802,11 @@ fn structFieldInits(...@@ -36812,11 +36802,11 @@ fn structFieldInits(
3681236802
36813 assert(!struct_type.haveFieldInits(ip));36803 assert(!struct_type.haveFieldInits(ip));
3681436804
36815 const cau_index = struct_type.cau.unwrap().?;36805 const cau_index = struct_type.cau;
36816 const namespace_index = ip.getCau(cau_index).namespace;36806 const namespace_index = ip.getCau(cau_index).namespace;
36817 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;36807 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
36818 const zir_index = struct_type.zir_index.unwrap().?.resolve(ip) orelse return error.AnalysisFail;36808 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
36819 const fields_len, const small, var extra_index = structZirInfo(zir, zir_index);36809 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);
3682036810
36821 var block_scope: Block = .{36811 var block_scope: Block = .{
36822 .parent = null,36812 .parent = null,
...@@ -36825,7 +36815,7 @@ fn structFieldInits(...@@ -36825,7 +36815,7 @@ fn structFieldInits(
36825 .instructions = .{},36815 .instructions = .{},
36826 .inlining = null,36816 .inlining = null,
36827 .is_comptime = true,36817 .is_comptime = true,
36828 .src_base_inst = struct_type.zir_index.unwrap().?,36818 .src_base_inst = struct_type.zir_index,
36829 .type_name_ctx = struct_type.name,36819 .type_name_ctx = struct_type.name,
36830 };36820 };
36831 defer assert(block_scope.instructions.items.len == 0);36821 defer assert(block_scope.instructions.items.len == 0);
...@@ -36860,10 +36850,7 @@ fn structFieldInits(...@@ -36860,10 +36850,7 @@ fn structFieldInits(
36860 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;36850 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
36861 cur_bit_bag >>= 1;36851 cur_bit_bag >>= 1;
3686236852
36863 if (!small.is_tuple) {36853 extra_index += 2; // field_name, doc_comment
36864 extra_index += 1;
36865 }
36866 extra_index += 1; // doc_comment
3686736854
36868 fields[field_i] = .{};36855 fields[field_i] = .{};
3686936856
...@@ -36901,7 +36888,7 @@ fn structFieldInits(...@@ -36901,7 +36888,7 @@ fn structFieldInits(
36901 sema.inst_map.putAssumeCapacity(zir_index, type_ref);36888 sema.inst_map.putAssumeCapacity(zir_index, type_ref);
3690236889
36903 const init_src: LazySrcLoc = .{36890 const init_src: LazySrcLoc = .{
36904 .base_node_inst = struct_type.zir_index.unwrap().?,36891 .base_node_inst = struct_type.zir_index,
36905 .offset = .{ .container_field_value = @intCast(field_i) },36892 .offset = .{ .container_field_value = @intCast(field_i) },
36906 };36893 };
3690736894
...@@ -37430,7 +37417,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37430,7 +37417,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37430 .undefined_type => Value.undef,37417 .undefined_type => Value.undef,
37431 .optional_noreturn_type => try pt.nullValue(ty),37418 .optional_noreturn_type => try pt.nullValue(ty),
37432 .generic_poison_type => error.GenericPoison,37419 .generic_poison_type => error.GenericPoison,
37433 .empty_struct_type => Value.empty_struct,37420 .empty_tuple_type => Value.empty_tuple,
37434 // values, not types37421 // values, not types
37435 .undef,37422 .undef,
37436 .zero,37423 .zero,
...@@ -37446,7 +37433,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37446,7 +37433,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37446 .null_value,37433 .null_value,
37447 .bool_true,37434 .bool_true,
37448 .bool_false,37435 .bool_false,
37449 .empty_struct,37436 .empty_tuple,
37450 .generic_poison,37437 .generic_poison,
37451 // invalid37438 // invalid
37452 .none,37439 .none,
...@@ -37532,10 +37519,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37532,10 +37519,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37532 .type_enum_explicit,37519 .type_enum_explicit,
37533 .type_enum_nonexhaustive,37520 .type_enum_nonexhaustive,
37534 .type_struct,37521 .type_struct,
37535 .type_struct_anon,
37536 .type_struct_packed,37522 .type_struct_packed,
37537 .type_struct_packed_inits,37523 .type_struct_packed_inits,
37538 .type_tuple_anon,37524 .type_tuple,
37539 .type_union,37525 .type_union,
37540 => switch (ip.indexToKey(ty.toIntern())) {37526 => switch (ip.indexToKey(ty.toIntern())) {
37541 inline .array_type, .vector_type => |seq_type, seq_tag| {37527 inline .array_type, .vector_type => |seq_type, seq_tag| {
...@@ -37594,7 +37580,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37594,7 +37580,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37594 } }));37580 } }));
37595 },37581 },
3759637582
37597 .anon_struct_type => |tuple| {37583 .tuple_type => |tuple| {
37598 for (tuple.values.get(ip)) |val| {37584 for (tuple.values.get(ip)) |val| {
37599 if (val == .none) return null;37585 if (val == .none) return null;
37600 }37586 }
...@@ -37965,35 +37951,9 @@ fn structFieldIndex(...@@ -37965,35 +37951,9 @@ fn structFieldIndex(
37965 const zcu = pt.zcu;37951 const zcu = pt.zcu;
37966 const ip = &zcu.intern_pool;37952 const ip = &zcu.intern_pool;
37967 try struct_ty.resolveFields(pt);37953 try struct_ty.resolveFields(pt);
37968 if (struct_ty.isAnonStruct(zcu)) {37954 const struct_type = zcu.typeToStruct(struct_ty).?;
37969 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);37955 return struct_type.nameIndex(ip, field_name) orelse
37970 } else {37956 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_src, field_name);
37971 const struct_type = zcu.typeToStruct(struct_ty).?;
37972 return struct_type.nameIndex(ip, field_name) orelse
37973 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_src, field_name);
37974 }
37975}
37976
37977fn anonStructFieldIndex(
37978 sema: *Sema,
37979 block: *Block,
37980 struct_ty: Type,
37981 field_name: InternPool.NullTerminatedString,
37982 field_src: LazySrcLoc,
37983) !u32 {
37984 const pt = sema.pt;
37985 const zcu = pt.zcu;
37986 const ip = &zcu.intern_pool;
37987 switch (ip.indexToKey(struct_ty.toIntern())) {
37988 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names.get(ip), 0..) |name, i| {
37989 if (name == field_name) return @intCast(i);
37990 },
37991 .struct_type => if (ip.loadStructType(struct_ty.toIntern()).nameIndex(ip, field_name)) |i| return i,
37992 else => unreachable,
37993 }
37994 return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{
37995 field_name.fmt(ip), struct_ty.fmt(pt),
37996 });
37997}37957}
3799837958
37999/// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting37959/// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting
src/Sema/bitcast.zig+1-1
...@@ -246,7 +246,7 @@ const UnpackValueBits = struct {...@@ -246,7 +246,7 @@ const UnpackValueBits = struct {
246 .error_union_type,246 .error_union_type,
247 .simple_type,247 .simple_type,
248 .struct_type,248 .struct_type,
249 .anon_struct_type,249 .tuple_type,
250 .union_type,250 .union_type,
251 .opaque_type,251 .opaque_type,
252 .enum_type,252 .enum_type,
src/Type.zig+63-115
...@@ -320,33 +320,20 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error...@@ -320,33 +320,20 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
320 },320 },
321 .struct_type => {321 .struct_type => {
322 const name = ip.loadStructType(ty.toIntern()).name;322 const name = ip.loadStructType(ty.toIntern()).name;
323 if (name == .empty) {323 try writer.print("{}", .{name.fmt(ip)});
324 try writer.writeAll("@TypeOf(.{})");
325 } else {
326 try writer.print("{}", .{name.fmt(ip)});
327 }
328 },324 },
329 .anon_struct_type => |anon_struct| {325 .tuple_type => |tuple| {
330 if (anon_struct.types.len == 0) {326 if (tuple.types.len == 0) {
331 return writer.writeAll("@TypeOf(.{})");327 return writer.writeAll("@TypeOf(.{})");
332 }328 }
333 try writer.writeAll("struct{");329 try writer.writeAll("struct {");
334 for (anon_struct.types.get(ip), anon_struct.values.get(ip), 0..) |field_ty, val, i| {330 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, val, i| {
335 if (i != 0) try writer.writeAll(", ");331 try writer.writeAll(if (i == 0) " " else ", ");
336 if (val != .none) {332 if (val != .none) try writer.writeAll("comptime ");
337 try writer.writeAll("comptime ");
338 }
339 if (anon_struct.names.len != 0) {
340 try writer.print("{}: ", .{anon_struct.names.get(ip)[i].fmt(&zcu.intern_pool)});
341 }
342
343 try print(Type.fromInterned(field_ty), writer, pt);333 try print(Type.fromInterned(field_ty), writer, pt);
344334 if (val != .none) try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(pt)});
345 if (val != .none) {
346 try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(pt)});
347 }
348 }335 }
349 try writer.writeAll("}");336 try writer.writeAll(" }");
350 },337 },
351338
352 .union_type => {339 .union_type => {
...@@ -489,8 +476,7 @@ pub fn hasRuntimeBitsInner(...@@ -489,8 +476,7 @@ pub fn hasRuntimeBitsInner(
489) RuntimeBitsError!bool {476) RuntimeBitsError!bool {
490 const ip = &zcu.intern_pool;477 const ip = &zcu.intern_pool;
491 return switch (ty.toIntern()) {478 return switch (ty.toIntern()) {
492 // False because it is a comptime-only type.479 .empty_tuple_type => false,
493 .empty_struct_type => false,
494 else => switch (ip.indexToKey(ty.toIntern())) {480 else => switch (ip.indexToKey(ty.toIntern())) {
495 .int_type => |int_type| int_type.bits != 0,481 .int_type => |int_type| int_type.bits != 0,
496 .ptr_type => {482 .ptr_type => {
...@@ -593,7 +579,7 @@ pub fn hasRuntimeBitsInner(...@@ -593,7 +579,7 @@ pub fn hasRuntimeBitsInner(
593 return false;579 return false;
594 }580 }
595 },581 },
596 .anon_struct_type => |tuple| {582 .tuple_type => |tuple| {
597 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {583 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
598 if (val != .none) continue; // comptime field584 if (val != .none) continue; // comptime field
599 if (try Type.fromInterned(field_ty).hasRuntimeBitsInner(585 if (try Type.fromInterned(field_ty).hasRuntimeBitsInner(
...@@ -691,7 +677,7 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {...@@ -691,7 +677,7 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {
691 .error_union_type,677 .error_union_type,
692 .error_set_type,678 .error_set_type,
693 .inferred_error_set_type,679 .inferred_error_set_type,
694 .anon_struct_type,680 .tuple_type,
695 .opaque_type,681 .opaque_type,
696 .anyframe_type,682 .anyframe_type,
697 // These are function bodies, not function pointers.683 // These are function bodies, not function pointers.
...@@ -966,7 +952,7 @@ pub fn abiAlignmentInner(...@@ -966,7 +952,7 @@ pub fn abiAlignmentInner(
966 const ip = &zcu.intern_pool;952 const ip = &zcu.intern_pool;
967953
968 switch (ty.toIntern()) {954 switch (ty.toIntern()) {
969 .empty_struct_type => return .{ .scalar = .@"1" },955 .empty_tuple_type => return .{ .scalar = .@"1" },
970 else => switch (ip.indexToKey(ty.toIntern())) {956 else => switch (ip.indexToKey(ty.toIntern())) {
971 .int_type => |int_type| {957 .int_type => |int_type| {
972 if (int_type.bits == 0) return .{ .scalar = .@"1" };958 if (int_type.bits == 0) return .{ .scalar = .@"1" };
...@@ -1109,7 +1095,7 @@ pub fn abiAlignmentInner(...@@ -1109,7 +1095,7 @@ pub fn abiAlignmentInner(
11091095
1110 return .{ .scalar = struct_type.flagsUnordered(ip).alignment };1096 return .{ .scalar = struct_type.flagsUnordered(ip).alignment };
1111 },1097 },
1112 .anon_struct_type => |tuple| {1098 .tuple_type => |tuple| {
1113 var big_align: Alignment = .@"1";1099 var big_align: Alignment = .@"1";
1114 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {1100 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
1115 if (val != .none) continue; // comptime field1101 if (val != .none) continue; // comptime field
...@@ -1295,7 +1281,7 @@ pub fn abiSizeInner(...@@ -1295,7 +1281,7 @@ pub fn abiSizeInner(
1295 const ip = &zcu.intern_pool;1281 const ip = &zcu.intern_pool;
12961282
1297 switch (ty.toIntern()) {1283 switch (ty.toIntern()) {
1298 .empty_struct_type => return .{ .scalar = 0 },1284 .empty_tuple_type => return .{ .scalar = 0 },
12991285
1300 else => switch (ip.indexToKey(ty.toIntern())) {1286 else => switch (ip.indexToKey(ty.toIntern())) {
1301 .int_type => |int_type| {1287 .int_type => |int_type| {
...@@ -1498,7 +1484,7 @@ pub fn abiSizeInner(...@@ -1498,7 +1484,7 @@ pub fn abiSizeInner(
1498 },1484 },
1499 }1485 }
1500 },1486 },
1501 .anon_struct_type => |tuple| {1487 .tuple_type => |tuple| {
1502 switch (strat) {1488 switch (strat) {
1503 .sema => try ty.resolveLayout(strat.pt(zcu, tid)),1489 .sema => try ty.resolveLayout(strat.pt(zcu, tid)),
1504 .lazy, .eager => {},1490 .lazy, .eager => {},
...@@ -1831,8 +1817,7 @@ pub fn bitSizeInner(...@@ -1831,8 +1817,7 @@ pub fn bitSizeInner(
1831 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;1817 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;
1832 },1818 },
18331819
1834 .anon_struct_type => {1820 .tuple_type => {
1835 if (strat == .sema) try ty.resolveFields(strat.pt(zcu, tid));
1836 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;1821 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;
1837 },1822 },
18381823
...@@ -2176,7 +2161,7 @@ pub fn containerLayout(ty: Type, zcu: *const Zcu) std.builtin.Type.ContainerLayo...@@ -2176,7 +2161,7 @@ pub fn containerLayout(ty: Type, zcu: *const Zcu) std.builtin.Type.ContainerLayo
2176 const ip = &zcu.intern_pool;2161 const ip = &zcu.intern_pool;
2177 return switch (ip.indexToKey(ty.toIntern())) {2162 return switch (ip.indexToKey(ty.toIntern())) {
2178 .struct_type => ip.loadStructType(ty.toIntern()).layout,2163 .struct_type => ip.loadStructType(ty.toIntern()).layout,
2179 .anon_struct_type => .auto,2164 .tuple_type => .auto,
2180 .union_type => ip.loadUnionType(ty.toIntern()).flagsUnordered(ip).layout,2165 .union_type => ip.loadUnionType(ty.toIntern()).flagsUnordered(ip).layout,
2181 else => unreachable,2166 else => unreachable,
2182 };2167 };
...@@ -2295,7 +2280,7 @@ pub fn arrayLenIncludingSentinel(ty: Type, zcu: *const Zcu) u64 {...@@ -2295,7 +2280,7 @@ pub fn arrayLenIncludingSentinel(ty: Type, zcu: *const Zcu) u64 {
2295pub fn vectorLen(ty: Type, zcu: *const Zcu) u32 {2280pub fn vectorLen(ty: Type, zcu: *const Zcu) u32 {
2296 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {2281 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
2297 .vector_type => |vector_type| vector_type.len,2282 .vector_type => |vector_type| vector_type.len,
2298 .anon_struct_type => |tuple| @intCast(tuple.types.len),2283 .tuple_type => |tuple| @intCast(tuple.types.len),
2299 else => unreachable,2284 else => unreachable,
2300 };2285 };
2301}2286}
...@@ -2305,7 +2290,7 @@ pub fn sentinel(ty: Type, zcu: *const Zcu) ?Value {...@@ -2305,7 +2290,7 @@ pub fn sentinel(ty: Type, zcu: *const Zcu) ?Value {
2305 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {2290 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
2306 .vector_type,2291 .vector_type,
2307 .struct_type,2292 .struct_type,
2308 .anon_struct_type,2293 .tuple_type,
2309 => null,2294 => null,
23102295
2311 .array_type => |t| if (t.sentinel != .none) Value.fromInterned(t.sentinel) else null,2296 .array_type => |t| if (t.sentinel != .none) Value.fromInterned(t.sentinel) else null,
...@@ -2386,7 +2371,7 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {...@@ -2386,7 +2371,7 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
2386 return .{ .signedness = .unsigned, .bits = zcu.errorSetBits() };2371 return .{ .signedness = .unsigned, .bits = zcu.errorSetBits() };
2387 },2372 },
23882373
2389 .anon_struct_type => unreachable,2374 .tuple_type => unreachable,
23902375
2391 .ptr_type => unreachable,2376 .ptr_type => unreachable,
2392 .anyframe_type => unreachable,2377 .anyframe_type => unreachable,
...@@ -2556,7 +2541,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {...@@ -2556,7 +2541,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
2556 var ty = starting_type;2541 var ty = starting_type;
2557 const ip = &zcu.intern_pool;2542 const ip = &zcu.intern_pool;
2558 while (true) switch (ty.toIntern()) {2543 while (true) switch (ty.toIntern()) {
2559 .empty_struct_type => return Value.empty_struct,2544 .empty_tuple_type => return Value.empty_tuple,
25602545
2561 else => switch (ip.indexToKey(ty.toIntern())) {2546 else => switch (ip.indexToKey(ty.toIntern())) {
2562 .int_type => |int_type| {2547 .int_type => |int_type| {
...@@ -2660,7 +2645,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {...@@ -2660,7 +2645,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
2660 } }));2645 } }));
2661 },2646 },
26622647
2663 .anon_struct_type => |tuple| {2648 .tuple_type => |tuple| {
2664 for (tuple.values.get(ip)) |val| {2649 for (tuple.values.get(ip)) |val| {
2665 if (val == .none) return null;2650 if (val == .none) return null;
2666 }2651 }
...@@ -2783,7 +2768,7 @@ pub fn comptimeOnlyInner(...@@ -2783,7 +2768,7 @@ pub fn comptimeOnlyInner(
2783) SemaError!bool {2768) SemaError!bool {
2784 const ip = &zcu.intern_pool;2769 const ip = &zcu.intern_pool;
2785 return switch (ty.toIntern()) {2770 return switch (ty.toIntern()) {
2786 .empty_struct_type => false,2771 .empty_tuple_type => false,
27872772
2788 else => switch (ip.indexToKey(ty.toIntern())) {2773 else => switch (ip.indexToKey(ty.toIntern())) {
2789 .int_type => false,2774 .int_type => false,
...@@ -2891,7 +2876,7 @@ pub fn comptimeOnlyInner(...@@ -2891,7 +2876,7 @@ pub fn comptimeOnlyInner(
2891 };2876 };
2892 },2877 },
28932878
2894 .anon_struct_type => |tuple| {2879 .tuple_type => |tuple| {
2895 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {2880 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
2896 const have_comptime_val = val != .none;2881 const have_comptime_val = val != .none;
2897 if (!have_comptime_val and try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) return true;2882 if (!have_comptime_val and try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) return true;
...@@ -3022,7 +3007,7 @@ pub fn getNamespace(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex {...@@ -3022,7 +3007,7 @@ pub fn getNamespace(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex {
3022 const ip = &zcu.intern_pool;3007 const ip = &zcu.intern_pool;
3023 return switch (ip.indexToKey(ty.toIntern())) {3008 return switch (ip.indexToKey(ty.toIntern())) {
3024 .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace.toOptional(),3009 .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace.toOptional(),
3025 .struct_type => ip.loadStructType(ty.toIntern()).namespace,3010 .struct_type => ip.loadStructType(ty.toIntern()).namespace.toOptional(),
3026 .union_type => ip.loadUnionType(ty.toIntern()).namespace.toOptional(),3011 .union_type => ip.loadUnionType(ty.toIntern()).namespace.toOptional(),
3027 .enum_type => ip.loadEnumType(ty.toIntern()).namespace.toOptional(),3012 .enum_type => ip.loadEnumType(ty.toIntern()).namespace.toOptional(),
3028 else => .none,3013 else => .none,
...@@ -3181,7 +3166,7 @@ pub fn structFieldName(ty: Type, index: usize, zcu: *const Zcu) InternPool.Optio...@@ -3181,7 +3166,7 @@ pub fn structFieldName(ty: Type, index: usize, zcu: *const Zcu) InternPool.Optio
3181 const ip = &zcu.intern_pool;3166 const ip = &zcu.intern_pool;
3182 return switch (ip.indexToKey(ty.toIntern())) {3167 return switch (ip.indexToKey(ty.toIntern())) {
3183 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index),3168 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index),
3184 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, index),3169 .tuple_type => .none,
3185 else => unreachable,3170 else => unreachable,
3186 };3171 };
3187}3172}
...@@ -3190,7 +3175,7 @@ pub fn structFieldCount(ty: Type, zcu: *const Zcu) u32 {...@@ -3190,7 +3175,7 @@ pub fn structFieldCount(ty: Type, zcu: *const Zcu) u32 {
3190 const ip = &zcu.intern_pool;3175 const ip = &zcu.intern_pool;
3191 return switch (ip.indexToKey(ty.toIntern())) {3176 return switch (ip.indexToKey(ty.toIntern())) {
3192 .struct_type => ip.loadStructType(ty.toIntern()).field_types.len,3177 .struct_type => ip.loadStructType(ty.toIntern()).field_types.len,
3193 .anon_struct_type => |anon_struct| anon_struct.types.len,3178 .tuple_type => |tuple| tuple.types.len,
3194 else => unreachable,3179 else => unreachable,
3195 };3180 };
3196}3181}
...@@ -3204,7 +3189,7 @@ pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type {...@@ -3204,7 +3189,7 @@ pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type {
3204 const union_obj = ip.loadUnionType(ty.toIntern());3189 const union_obj = ip.loadUnionType(ty.toIntern());
3205 return Type.fromInterned(union_obj.field_types.get(ip)[index]);3190 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
3206 },3191 },
3207 .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]),3192 .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]),
3208 else => unreachable,3193 else => unreachable,
3209 };3194 };
3210}3195}
...@@ -3238,8 +3223,8 @@ pub fn fieldAlignmentInner(...@@ -3238,8 +3223,8 @@ pub fn fieldAlignmentInner(
3238 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);3223 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);
3239 return field_ty.structFieldAlignmentInner(explicit_align, struct_type.layout, strat, zcu, tid);3224 return field_ty.structFieldAlignmentInner(explicit_align, struct_type.layout, strat, zcu, tid);
3240 },3225 },
3241 .anon_struct_type => |anon_struct| {3226 .tuple_type => |tuple| {
3242 return (try Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignmentInner(3227 return (try Type.fromInterned(tuple.types.get(ip)[index]).abiAlignmentInner(
3243 strat.toLazy(),3228 strat.toLazy(),
3244 zcu,3229 zcu,
3245 tid,3230 tid,
...@@ -3361,8 +3346,8 @@ pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) Value {...@@ -3361,8 +3346,8 @@ pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) Value {
3361 if (val == .none) return Value.@"unreachable";3346 if (val == .none) return Value.@"unreachable";
3362 return Value.fromInterned(val);3347 return Value.fromInterned(val);
3363 },3348 },
3364 .anon_struct_type => |anon_struct| {3349 .tuple_type => |tuple| {
3365 const val = anon_struct.values.get(ip)[index];3350 const val = tuple.values.get(ip)[index];
3366 // TODO: avoid using `unreachable` to indicate this.3351 // TODO: avoid using `unreachable` to indicate this.
3367 if (val == .none) return Value.@"unreachable";3352 if (val == .none) return Value.@"unreachable";
3368 return Value.fromInterned(val);3353 return Value.fromInterned(val);
...@@ -3384,7 +3369,7 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val...@@ -3384,7 +3369,7 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val
3384 return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(pt);3369 return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(pt);
3385 }3370 }
3386 },3371 },
3387 .anon_struct_type => |tuple| {3372 .tuple_type => |tuple| {
3388 const val = tuple.values.get(ip)[index];3373 const val = tuple.values.get(ip)[index];
3389 if (val == .none) {3374 if (val == .none) {
3390 return Type.fromInterned(tuple.types.get(ip)[index]).onePossibleValue(pt);3375 return Type.fromInterned(tuple.types.get(ip)[index]).onePossibleValue(pt);
...@@ -3400,7 +3385,7 @@ pub fn structFieldIsComptime(ty: Type, index: usize, zcu: *const Zcu) bool {...@@ -3400,7 +3385,7 @@ pub fn structFieldIsComptime(ty: Type, index: usize, zcu: *const Zcu) bool {
3400 const ip = &zcu.intern_pool;3385 const ip = &zcu.intern_pool;
3401 return switch (ip.indexToKey(ty.toIntern())) {3386 return switch (ip.indexToKey(ty.toIntern())) {
3402 .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index),3387 .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index),
3403 .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,3388 .tuple_type => |tuple| tuple.values.get(ip)[index] != .none,
3404 else => unreachable,3389 else => unreachable,
3405 };3390 };
3406}3391}
...@@ -3425,7 +3410,7 @@ pub fn structFieldOffset(...@@ -3425,7 +3410,7 @@ pub fn structFieldOffset(
3425 return struct_type.offsets.get(ip)[index];3410 return struct_type.offsets.get(ip)[index];
3426 },3411 },
34273412
3428 .anon_struct_type => |tuple| {3413 .tuple_type => |tuple| {
3429 var offset: u64 = 0;3414 var offset: u64 = 0;
3430 var big_align: Alignment = .none;3415 var big_align: Alignment = .none;
34313416
...@@ -3472,7 +3457,6 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc {...@@ -3472,7 +3457,6 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc {
3472 .declared => |d| d.zir_index,3457 .declared => |d| d.zir_index,
3473 .reified => |r| r.zir_index,3458 .reified => |r| r.zir_index,
3474 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,3459 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
3475 .empty_struct => return null,
3476 },3460 },
3477 else => return null,3461 else => return null,
3478 },3462 },
...@@ -3491,49 +3475,7 @@ pub fn isGenericPoison(ty: Type) bool {...@@ -3491,49 +3475,7 @@ pub fn isGenericPoison(ty: Type) bool {
3491pub fn isTuple(ty: Type, zcu: *const Zcu) bool {3475pub fn isTuple(ty: Type, zcu: *const Zcu) bool {
3492 const ip = &zcu.intern_pool;3476 const ip = &zcu.intern_pool;
3493 return switch (ip.indexToKey(ty.toIntern())) {3477 return switch (ip.indexToKey(ty.toIntern())) {
3494 .struct_type => {3478 .tuple_type => true,
3495 const struct_type = ip.loadStructType(ty.toIntern());
3496 if (struct_type.layout == .@"packed") return false;
3497 if (struct_type.cau == .none) return false;
3498 return struct_type.flagsUnordered(ip).is_tuple;
3499 },
3500 .anon_struct_type => |anon_struct| anon_struct.names.len == 0,
3501 else => false,
3502 };
3503}
3504
3505pub fn isAnonStruct(ty: Type, zcu: *const Zcu) bool {
3506 if (ty.toIntern() == .empty_struct_type) return true;
3507 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
3508 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len > 0,
3509 else => false,
3510 };
3511}
3512
3513pub fn isTupleOrAnonStruct(ty: Type, zcu: *const Zcu) bool {
3514 const ip = &zcu.intern_pool;
3515 return switch (ip.indexToKey(ty.toIntern())) {
3516 .struct_type => {
3517 const struct_type = ip.loadStructType(ty.toIntern());
3518 if (struct_type.layout == .@"packed") return false;
3519 if (struct_type.cau == .none) return false;
3520 return struct_type.flagsUnordered(ip).is_tuple;
3521 },
3522 .anon_struct_type => true,
3523 else => false,
3524 };
3525}
3526
3527pub fn isSimpleTuple(ty: Type, zcu: *const Zcu) bool {
3528 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
3529 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
3530 else => false,
3531 };
3532}
3533
3534pub fn isSimpleTupleOrAnonStruct(ty: Type, zcu: *const Zcu) bool {
3535 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
3536 .anon_struct_type => true,
3537 else => false,3479 else => false,
3538 };3480 };
3539}3481}
...@@ -3564,7 +3506,7 @@ pub fn toUnsigned(ty: Type, pt: Zcu.PerThread) !Type {...@@ -3564,7 +3506,7 @@ pub fn toUnsigned(ty: Type, pt: Zcu.PerThread) !Type {
3564pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {3506pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
3565 const ip = &zcu.intern_pool;3507 const ip = &zcu.intern_pool;
3566 return switch (ip.indexToKey(ty.toIntern())) {3508 return switch (ip.indexToKey(ty.toIntern())) {
3567 .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(),3509 .struct_type => ip.loadStructType(ty.toIntern()).zir_index,
3568 .union_type => ip.loadUnionType(ty.toIntern()).zir_index,3510 .union_type => ip.loadUnionType(ty.toIntern()).zir_index,
3569 .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(),3511 .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(),
3570 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,3512 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,
...@@ -3575,12 +3517,11 @@ pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {...@@ -3575,12 +3517,11 @@ pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
3575pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {3517pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
3576 const ip = &zcu.intern_pool;3518 const ip = &zcu.intern_pool;
3577 return switch (ip.indexToKey(ty.toIntern())) {3519 return switch (ip.indexToKey(ty.toIntern())) {
3578 .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(),3520 .struct_type => ip.loadStructType(ty.toIntern()).zir_index,
3579 .union_type => ip.loadUnionType(ty.toIntern()).zir_index,3521 .union_type => ip.loadUnionType(ty.toIntern()).zir_index,
3580 .enum_type => |e| switch (e) {3522 .enum_type => |e| switch (e) {
3581 .declared, .reified => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?,3523 .declared, .reified => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?,
3582 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,3524 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
3583 .empty_struct => unreachable,
3584 },3525 },
3585 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,3526 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,
3586 else => null,3527 else => null,
...@@ -3588,13 +3529,16 @@ pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.Trac...@@ -3588,13 +3529,16 @@ pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.Trac
3588}3529}
35893530
3590pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {3531pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
3532 // Note that changes to ZIR instruction tracking only need to update this code
3533 // if a newly-tracked instruction can be a type's owner `zir_index`.
3534 comptime assert(Zir.inst_tracking_version == 0);
3535
3591 const ip = &zcu.intern_pool;3536 const ip = &zcu.intern_pool;
3592 const tracked = switch (ip.indexToKey(ty.toIntern())) {3537 const tracked = switch (ip.indexToKey(ty.toIntern())) {
3593 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {3538 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
3594 .declared => |d| d.zir_index,3539 .declared => |d| d.zir_index,
3595 .reified => |r| r.zir_index,3540 .reified => |r| r.zir_index,
3596 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,3541 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
3597 .empty_struct => return null,
3598 },3542 },
3599 else => return null,3543 else => return null,
3600 };3544 };
...@@ -3603,13 +3547,17 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {...@@ -3603,13 +3547,17 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
3603 assert(file.zir_loaded);3547 assert(file.zir_loaded);
3604 const zir = file.zir;3548 const zir = file.zir;
3605 const inst = zir.instructions.get(@intFromEnum(info.inst));3549 const inst = zir.instructions.get(@intFromEnum(info.inst));
3606 assert(inst.tag == .extended);3550 return switch (inst.tag) {
3607 return switch (inst.data.extended.opcode) {3551 .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line,
3608 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_line,3552 .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_line,
3609 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,3553 .extended => switch (inst.data.extended.opcode) {
3610 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,3554 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_line,
3611 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,3555 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
3612 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line,3556 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
3557 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,
3558 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line,
3559 else => unreachable,
3560 },
3613 else => unreachable,3561 else => unreachable,
3614 };3562 };
3615}3563}
...@@ -3697,8 +3645,8 @@ pub fn resolveLayout(ty: Type, pt: Zcu.PerThread) SemaError!void {...@@ -3697,8 +3645,8 @@ pub fn resolveLayout(ty: Type, pt: Zcu.PerThread) SemaError!void {
3697 const ip = &zcu.intern_pool;3645 const ip = &zcu.intern_pool;
3698 switch (ty.zigTypeTag(zcu)) {3646 switch (ty.zigTypeTag(zcu)) {
3699 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {3647 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
3700 .anon_struct_type => |anon_struct_type| for (0..anon_struct_type.types.len) |i| {3648 .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| {
3701 const field_ty = Type.fromInterned(anon_struct_type.types.get(ip)[i]);3649 const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]);
3702 try field_ty.resolveLayout(pt);3650 try field_ty.resolveLayout(pt);
3703 },3651 },
3704 .struct_type => return ty.resolveStructInner(pt, .layout),3652 .struct_type => return ty.resolveStructInner(pt, .layout),
...@@ -3796,7 +3744,7 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {...@@ -3796,7 +3744,7 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
3796 .optional_noreturn_type,3744 .optional_noreturn_type,
3797 .anyerror_void_error_union_type,3745 .anyerror_void_error_union_type,
3798 .generic_poison_type,3746 .generic_poison_type,
3799 .empty_struct_type,3747 .empty_tuple_type,
3800 => {},3748 => {},
38013749
3802 .undef => unreachable,3750 .undef => unreachable,
...@@ -3813,7 +3761,7 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {...@@ -3813,7 +3761,7 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
3813 .null_value => unreachable,3761 .null_value => unreachable,
3814 .bool_true => unreachable,3762 .bool_true => unreachable,
3815 .bool_false => unreachable,3763 .bool_false => unreachable,
3816 .empty_struct => unreachable,3764 .empty_tuple => unreachable,
3817 .generic_poison => unreachable,3765 .generic_poison => unreachable,
38183766
3819 else => switch (ty_ip.unwrap(ip).getTag(ip)) {3767 else => switch (ty_ip.unwrap(ip).getTag(ip)) {
...@@ -3868,8 +3816,8 @@ pub fn resolveFully(ty: Type, pt: Zcu.PerThread) SemaError!void {...@@ -3868,8 +3816,8 @@ pub fn resolveFully(ty: Type, pt: Zcu.PerThread) SemaError!void {
3868 },3816 },
38693817
3870 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {3818 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
3871 .anon_struct_type => |anon_struct_type| for (0..anon_struct_type.types.len) |i| {3819 .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| {
3872 const field_ty = Type.fromInterned(anon_struct_type.types.get(ip)[i]);3820 const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]);
3873 try field_ty.resolveFully(pt);3821 try field_ty.resolveFully(pt);
3874 },3822 },
3875 .struct_type => return ty.resolveStructInner(pt, .full),3823 .struct_type => return ty.resolveStructInner(pt, .full),
...@@ -3903,7 +3851,7 @@ fn resolveStructInner(...@@ -3903,7 +3851,7 @@ fn resolveStructInner(
3903 const gpa = zcu.gpa;3851 const gpa = zcu.gpa;
39043852
3905 const struct_obj = zcu.typeToStruct(ty).?;3853 const struct_obj = zcu.typeToStruct(ty).?;
3906 const owner = InternPool.AnalUnit.wrap(.{ .cau = struct_obj.cau.unwrap() orelse return });3854 const owner = InternPool.AnalUnit.wrap(.{ .cau = struct_obj.cau });
39073855
3908 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {3856 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
3909 return error.AnalysisFail;3857 return error.AnalysisFail;
...@@ -3915,7 +3863,7 @@ fn resolveStructInner(...@@ -3915,7 +3863,7 @@ fn resolveStructInner(
3915 var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa);3863 var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa);
3916 defer comptime_err_ret_trace.deinit();3864 defer comptime_err_ret_trace.deinit();
39173865
3918 const zir = zcu.namespacePtr(struct_obj.namespace.unwrap().?).fileScope(zcu).zir;3866 const zir = zcu.namespacePtr(struct_obj.namespace).fileScope(zcu).zir;
3919 var sema: Sema = .{3867 var sema: Sema = .{
3920 .pt = pt,3868 .pt = pt,
3921 .gpa = gpa,3869 .gpa = gpa,
...@@ -4196,7 +4144,7 @@ pub const single_const_pointer_to_comptime_int: Type = .{...@@ -4196,7 +4144,7 @@ pub const single_const_pointer_to_comptime_int: Type = .{
4196 .ip_index = .single_const_pointer_to_comptime_int_type,4144 .ip_index = .single_const_pointer_to_comptime_int_type,
4197};4145};
4198pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };4146pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
4199pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };4147pub const empty_tuple_type: Type = .{ .ip_index = .empty_tuple_type };
42004148
4201pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };4149pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
42024150
src/Value.zig+1-1
...@@ -3704,7 +3704,7 @@ pub const @"unreachable": Value = .{ .ip_index = .unreachable_value };...@@ -3704,7 +3704,7 @@ pub const @"unreachable": Value = .{ .ip_index = .unreachable_value };
37043704
3705pub const generic_poison: Value = .{ .ip_index = .generic_poison };3705pub const generic_poison: Value = .{ .ip_index = .generic_poison };
3706pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };3706pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };
3707pub const empty_struct: Value = .{ .ip_index = .empty_struct };3707pub const empty_tuple: Value = .{ .ip_index = .empty_tuple };
37083708
3709pub fn makeBool(x: bool) Value {3709pub fn makeBool(x: bool) Value {
3710 return if (x) Value.true else Value.false;3710 return if (x) Value.true else Value.false;
src/Zcu.zig+33-2
...@@ -1497,6 +1497,20 @@ pub const SrcLoc = struct {...@@ -1497,6 +1497,20 @@ pub const SrcLoc = struct {
1497 }1497 }
1498 } else unreachable;1498 } else unreachable;
1499 },1499 },
1500 .tuple_field_type, .tuple_field_init => |field_info| {
1501 const tree = try src_loc.file_scope.getTree(gpa);
1502 const node = src_loc.relativeToNodeIndex(0);
1503 var buf: [2]Ast.Node.Index = undefined;
1504 const container_decl = tree.fullContainerDecl(&buf, node) orelse
1505 return tree.nodeToSpan(node);
1506
1507 const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?;
1508 return tree.nodeToSpan(switch (src_loc.lazy) {
1509 .tuple_field_type => field.ast.type_expr,
1510 .tuple_field_init => field.ast.value_expr,
1511 else => unreachable,
1512 });
1513 },
1500 .init_elem => |init_elem| {1514 .init_elem => |init_elem| {
1501 const tree = try src_loc.file_scope.getTree(gpa);1515 const tree = try src_loc.file_scope.getTree(gpa);
1502 const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset);1516 const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset);
...@@ -1939,6 +1953,12 @@ pub const LazySrcLoc = struct {...@@ -1939,6 +1953,12 @@ pub const LazySrcLoc = struct {
1939 container_field_type: u32,1953 container_field_type: u32,
1940 /// Like `continer_field_name`, but points at the field's alignment.1954 /// Like `continer_field_name`, but points at the field's alignment.
1941 container_field_align: u32,1955 container_field_align: u32,
1956 /// The source location points to the type of the field at the given index
1957 /// of the tuple type declaration at `tuple_decl_node_offset`.
1958 tuple_field_type: TupleField,
1959 /// The source location points to the default init of the field at the given index
1960 /// of the tuple type declaration at `tuple_decl_node_offset`.
1961 tuple_field_init: TupleField,
1942 /// The source location points to the given element/field of a struct or1962 /// The source location points to the given element/field of a struct or
1943 /// array initialization expression.1963 /// array initialization expression.
1944 init_elem: struct {1964 init_elem: struct {
...@@ -2016,13 +2036,20 @@ pub const LazySrcLoc = struct {...@@ -2016,13 +2036,20 @@ pub const LazySrcLoc = struct {
2016 index: u31,2036 index: u31,
2017 };2037 };
20182038
2019 const ArrayCat = struct {2039 pub const ArrayCat = struct {
2020 /// Points to the array concat AST node.2040 /// Points to the array concat AST node.
2021 array_cat_offset: i32,2041 array_cat_offset: i32,
2022 /// The index of the element the source location points to.2042 /// The index of the element the source location points to.
2023 elem_index: u32,2043 elem_index: u32,
2024 };2044 };
20252045
2046 pub const TupleField = struct {
2047 /// Points to the AST node of the tuple type decaration.
2048 tuple_decl_node_offset: i32,
2049 /// The index of the tuple field the source location points to.
2050 elem_index: u32,
2051 };
2052
2026 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;2053 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
20272054
2028 noinline fn nodeOffsetDebug(node_offset: i32) Offset {2055 noinline fn nodeOffsetDebug(node_offset: i32) Offset {
...@@ -2052,6 +2079,8 @@ pub const LazySrcLoc = struct {...@@ -2052,6 +2079,8 @@ pub const LazySrcLoc = struct {
20522079
2053 /// Returns `null` if the ZIR instruction has been lost across incremental updates.2080 /// Returns `null` if the ZIR instruction has been lost across incremental updates.
2054 pub fn resolveBaseNode(base_node_inst: InternPool.TrackedInst.Index, zcu: *Zcu) ?struct { *File, Ast.Node.Index } {2081 pub fn resolveBaseNode(base_node_inst: InternPool.TrackedInst.Index, zcu: *Zcu) ?struct { *File, Ast.Node.Index } {
2082 comptime assert(Zir.inst_tracking_version == 0);
2083
2055 const ip = &zcu.intern_pool;2084 const ip = &zcu.intern_pool;
2056 const file_index, const zir_inst = inst: {2085 const file_index, const zir_inst = inst: {
2057 const info = base_node_inst.resolveFull(ip) orelse return null;2086 const info = base_node_inst.resolveFull(ip) orelse return null;
...@@ -2064,6 +2093,8 @@ pub const LazySrcLoc = struct {...@@ -2064,6 +2093,8 @@ pub const LazySrcLoc = struct {
2064 const inst = zir.instructions.get(@intFromEnum(zir_inst));2093 const inst = zir.instructions.get(@intFromEnum(zir_inst));
2065 const base_node: Ast.Node.Index = switch (inst.tag) {2094 const base_node: Ast.Node.Index = switch (inst.tag) {
2066 .declaration => inst.data.declaration.src_node,2095 .declaration => inst.data.declaration.src_node,
2096 .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_node,
2097 .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_node,
2067 .extended => switch (inst.data.extended.opcode) {2098 .extended => switch (inst.data.extended.opcode) {
2068 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_node,2099 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_node,
2069 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,2100 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,
...@@ -3215,7 +3246,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3215,7 +3246,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
32153246
3216 // If this type has a `Cau` for resolution, it's automatically referenced.3247 // If this type has a `Cau` for resolution, it's automatically referenced.
3217 const resolution_cau: InternPool.Cau.Index.Optional = switch (ip.indexToKey(ty)) {3248 const resolution_cau: InternPool.Cau.Index.Optional = switch (ip.indexToKey(ty)) {
3218 .struct_type => ip.loadStructType(ty).cau,3249 .struct_type => ip.loadStructType(ty).cau.toOptional(),
3219 .union_type => ip.loadUnionType(ty).cau.toOptional(),3250 .union_type => ip.loadUnionType(ty).cau.toOptional(),
3220 .enum_type => ip.loadEnumType(ty).cau,3251 .enum_type => ip.loadEnumType(ty).cau,
3221 .opaque_type => .none,3252 .opaque_type => .none,
src/Zcu/PerThread.zig+7-15
...@@ -985,7 +985,6 @@ fn createFileRootStruct(...@@ -985,7 +985,6 @@ fn createFileRootStruct(
985 .fields_len = fields_len,985 .fields_len = fields_len,
986 .known_non_opv = small.known_non_opv,986 .known_non_opv = small.known_non_opv,
987 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,987 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
988 .is_tuple = small.is_tuple,
989 .any_comptime_fields = small.any_comptime_fields,988 .any_comptime_fields = small.any_comptime_fields,
990 .any_default_inits = small.any_default_inits,989 .any_default_inits = small.any_default_inits,
991 .inits_resolved = false,990 .inits_resolved = false,
...@@ -3191,7 +3190,7 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updat...@@ -3191,7 +3190,7 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updat
3191 .struct_type => |key| {3190 .struct_type => |key| {
3192 const struct_obj = ip.loadStructType(ty);3191 const struct_obj = ip.loadStructType(ty);
3193 const outdated = already_updating or o: {3192 const outdated = already_updating or o: {
3194 const anal_unit = AnalUnit.wrap(.{ .cau = struct_obj.cau.unwrap().? });3193 const anal_unit = AnalUnit.wrap(.{ .cau = struct_obj.cau });
3195 const o = zcu.outdated.swapRemove(anal_unit) or3194 const o = zcu.outdated.swapRemove(anal_unit) or
3196 zcu.potentially_outdated.swapRemove(anal_unit);3195 zcu.potentially_outdated.swapRemove(anal_unit);
3197 if (o) {3196 if (o) {
...@@ -3252,7 +3251,6 @@ fn recreateStructType(...@@ -3252,7 +3251,6 @@ fn recreateStructType(
32523251
3253 const key = switch (full_key) {3252 const key = switch (full_key) {
3254 .reified => unreachable, // never outdated3253 .reified => unreachable, // never outdated
3255 .empty_struct => unreachable, // never outdated
3256 .generated_tag => unreachable, // not a struct3254 .generated_tag => unreachable, // not a struct
3257 .declared => |d| d,3255 .declared => |d| d,
3258 };3256 };
...@@ -3283,16 +3281,13 @@ fn recreateStructType(...@@ -3283,16 +3281,13 @@ fn recreateStructType(
3283 if (captures_len != key.captures.owned.len) return error.AnalysisFail;3281 if (captures_len != key.captures.owned.len) return error.AnalysisFail;
32843282
3285 // The old type will be unused, so drop its dependency information.3283 // The old type will be unused, so drop its dependency information.
3286 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = struct_obj.cau.unwrap().? }));3284 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = struct_obj.cau }));
3287
3288 const namespace_index = struct_obj.namespace.unwrap().?;
32893285
3290 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{3286 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
3291 .layout = small.layout,3287 .layout = small.layout,
3292 .fields_len = fields_len,3288 .fields_len = fields_len,
3293 .known_non_opv = small.known_non_opv,3289 .known_non_opv = small.known_non_opv,
3294 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,3290 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
3295 .is_tuple = small.is_tuple,
3296 .any_comptime_fields = small.any_comptime_fields,3291 .any_comptime_fields = small.any_comptime_fields,
3297 .any_default_inits = small.any_default_inits,3292 .any_default_inits = small.any_default_inits,
3298 .inits_resolved = false,3293 .inits_resolved = false,
...@@ -3308,17 +3303,17 @@ fn recreateStructType(...@@ -3308,17 +3303,17 @@ fn recreateStructType(
3308 errdefer wip_ty.cancel(ip, pt.tid);3303 errdefer wip_ty.cancel(ip, pt.tid);
33093304
3310 wip_ty.setName(ip, struct_obj.name);3305 wip_ty.setName(ip, struct_obj.name);
3311 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, namespace_index, wip_ty.index);3306 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, struct_obj.namespace, wip_ty.index);
3312 try ip.addDependency(3307 try ip.addDependency(
3313 gpa,3308 gpa,
3314 AnalUnit.wrap(.{ .cau = new_cau_index }),3309 AnalUnit.wrap(.{ .cau = new_cau_index }),
3315 .{ .src_hash = key.zir_index },3310 .{ .src_hash = key.zir_index },
3316 );3311 );
3317 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;3312 zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;
3318 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.3313 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.
3319 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });3314 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
33203315
3321 const new_ty = wip_ty.finish(ip, new_cau_index.toOptional(), namespace_index);3316 const new_ty = wip_ty.finish(ip, new_cau_index.toOptional(), struct_obj.namespace);
3322 if (inst_info.inst == .main_struct_inst) {3317 if (inst_info.inst == .main_struct_inst) {
3323 // This is the root type of a file! Update the reference.3318 // This is the root type of a file! Update the reference.
3324 zcu.setFileRootType(inst_info.file, new_ty);3319 zcu.setFileRootType(inst_info.file, new_ty);
...@@ -3337,7 +3332,6 @@ fn recreateUnionType(...@@ -3337,7 +3332,6 @@ fn recreateUnionType(
33373332
3338 const key = switch (full_key) {3333 const key = switch (full_key) {
3339 .reified => unreachable, // never outdated3334 .reified => unreachable, // never outdated
3340 .empty_struct => unreachable, // never outdated
3341 .generated_tag => unreachable, // not a union3335 .generated_tag => unreachable, // not a union
3342 .declared => |d| d,3336 .declared => |d| d,
3343 };3337 };
...@@ -3429,9 +3423,7 @@ fn recreateEnumType(...@@ -3429,9 +3423,7 @@ fn recreateEnumType(
3429 const ip = &zcu.intern_pool;3423 const ip = &zcu.intern_pool;
34303424
3431 const key = switch (full_key) {3425 const key = switch (full_key) {
3432 .reified => unreachable, // never outdated3426 .reified, .generated_tag => unreachable, // never outdated
3433 .empty_struct => unreachable, // never outdated
3434 .generated_tag => unreachable, // never outdated
3435 .declared => |d| d,3427 .declared => |d| d,
3436 };3428 };
34373429
...@@ -3575,7 +3567,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace...@@ -3575,7 +3567,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
3575 };3567 };
35763568
3577 const key = switch (full_key) {3569 const key = switch (full_key) {
3578 .reified, .empty_struct, .generated_tag => {3570 .reified, .generated_tag => {
3579 // Namespace always empty, so up-to-date.3571 // Namespace always empty, so up-to-date.
3580 namespace.generation = zcu.generation;3572 namespace.generation = zcu.generation;
3581 return;3573 return;
src/arch/sparc64/CodeGen.zig+5-7
...@@ -3114,7 +3114,7 @@ fn binOpImmediate(...@@ -3114,7 +3114,7 @@ fn binOpImmediate(
3114 const reg = try self.register_manager.allocReg(track_inst, gp);3114 const reg = try self.register_manager.allocReg(track_inst, gp);
31153115
3116 if (track_inst) |inst| {3116 if (track_inst) |inst| {
3117 const mcv = .{ .register = reg };3117 const mcv: MCValue = .{ .register = reg };
3118 log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv });3118 log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv });
3119 branch.inst_table.putAssumeCapacity(inst, mcv);3119 branch.inst_table.putAssumeCapacity(inst, mcv);
31203120
...@@ -3252,7 +3252,7 @@ fn binOpRegister(...@@ -3252,7 +3252,7 @@ fn binOpRegister(
32523252
3253 const reg = try self.register_manager.allocReg(track_inst, gp);3253 const reg = try self.register_manager.allocReg(track_inst, gp);
3254 if (track_inst) |inst| {3254 if (track_inst) |inst| {
3255 const mcv = .{ .register = reg };3255 const mcv: MCValue = .{ .register = reg };
3256 log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv });3256 log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv });
3257 branch.inst_table.putAssumeCapacity(inst, mcv);3257 branch.inst_table.putAssumeCapacity(inst, mcv);
32583258
...@@ -3276,7 +3276,7 @@ fn binOpRegister(...@@ -3276,7 +3276,7 @@ fn binOpRegister(
32763276
3277 const reg = try self.register_manager.allocReg(track_inst, gp);3277 const reg = try self.register_manager.allocReg(track_inst, gp);
3278 if (track_inst) |inst| {3278 if (track_inst) |inst| {
3279 const mcv = .{ .register = reg };3279 const mcv: MCValue = .{ .register = reg };
3280 log.debug("binOpRegister move rhs %{d} to register: {} -> {}", .{ inst, rhs, mcv });3280 log.debug("binOpRegister move rhs %{d} to register: {} -> {}", .{ inst, rhs, mcv });
3281 branch.inst_table.putAssumeCapacity(inst, mcv);3281 branch.inst_table.putAssumeCapacity(inst, mcv);
32823282
...@@ -3650,7 +3650,6 @@ fn genLoad(self: *Self, value_reg: Register, addr_reg: Register, comptime off_ty...@@ -3650,7 +3650,6 @@ fn genLoad(self: *Self, value_reg: Register, addr_reg: Register, comptime off_ty
3650 assert(off_type == Register or off_type == i13);3650 assert(off_type == Register or off_type == i13);
36513651
3652 const is_imm = (off_type == i13);3652 const is_imm = (off_type == i13);
3653 const rs2_or_imm = if (is_imm) .{ .imm = off } else .{ .rs2 = off };
36543653
3655 switch (abi_size) {3654 switch (abi_size) {
3656 1, 2, 4, 8 => {3655 1, 2, 4, 8 => {
...@@ -3669,7 +3668,7 @@ fn genLoad(self: *Self, value_reg: Register, addr_reg: Register, comptime off_ty...@@ -3669,7 +3668,7 @@ fn genLoad(self: *Self, value_reg: Register, addr_reg: Register, comptime off_ty
3669 .is_imm = is_imm,3668 .is_imm = is_imm,
3670 .rd = value_reg,3669 .rd = value_reg,
3671 .rs1 = addr_reg,3670 .rs1 = addr_reg,
3672 .rs2_or_imm = rs2_or_imm,3671 .rs2_or_imm = if (is_imm) .{ .imm = off } else .{ .rs2 = off },
3673 },3672 },
3674 },3673 },
3675 });3674 });
...@@ -4037,7 +4036,6 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t...@@ -4037,7 +4036,6 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t
4037 assert(off_type == Register or off_type == i13);4036 assert(off_type == Register or off_type == i13);
40384037
4039 const is_imm = (off_type == i13);4038 const is_imm = (off_type == i13);
4040 const rs2_or_imm = if (is_imm) .{ .imm = off } else .{ .rs2 = off };
40414039
4042 switch (abi_size) {4040 switch (abi_size) {
4043 1, 2, 4, 8 => {4041 1, 2, 4, 8 => {
...@@ -4056,7 +4054,7 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t...@@ -4056,7 +4054,7 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t
4056 .is_imm = is_imm,4054 .is_imm = is_imm,
4057 .rd = value_reg,4055 .rd = value_reg,
4058 .rs1 = addr_reg,4056 .rs1 = addr_reg,
4059 .rs2_or_imm = rs2_or_imm,4057 .rs2_or_imm = if (is_imm) .{ .imm = off } else .{ .rs2 = off },
4060 },4058 },
4061 },4059 },
4062 });4060 });
src/arch/wasm/CodeGen.zig+3-3
...@@ -3259,7 +3259,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3259,7 +3259,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3259 .error_union_type,3259 .error_union_type,
3260 .simple_type,3260 .simple_type,
3261 .struct_type,3261 .struct_type,
3262 .anon_struct_type,3262 .tuple_type,
3263 .union_type,3263 .union_type,
3264 .opaque_type,3264 .opaque_type,
3265 .enum_type,3265 .enum_type,
...@@ -3273,7 +3273,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3273,7 +3273,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3273 .undefined,3273 .undefined,
3274 .void,3274 .void,
3275 .null,3275 .null,
3276 .empty_struct,3276 .empty_tuple,
3277 .@"unreachable",3277 .@"unreachable",
3278 .generic_poison,3278 .generic_poison,
3279 => unreachable, // non-runtime values3279 => unreachable, // non-runtime values
...@@ -3708,7 +3708,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3708,7 +3708,7 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3708 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;3708 const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
3709 const operand = try func.resolveInst(un_op);3709 const operand = try func.resolveInst(un_op);
3710 const sym_index = try func.bin_file.getGlobalSymbol("__zig_errors_len", null);3710 const sym_index = try func.bin_file.getGlobalSymbol("__zig_errors_len", null);
3711 const errors_len = .{ .memory = @intFromEnum(sym_index) };3711 const errors_len: WValue = .{ .memory = @intFromEnum(sym_index) };
37123712
3713 try func.emitWValue(operand);3713 try func.emitWValue(operand);
3714 const pt = func.pt;3714 const pt = func.pt;
src/arch/x86_64/CodeGen.zig+1-1
...@@ -13683,7 +13683,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -13683,7 +13683,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
13683 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;13683 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
13684 const operand = try self.resolveInst(un_op);13684 const operand = try self.resolveInst(un_op);
13685 const ty = self.typeOf(un_op);13685 const ty = self.typeOf(un_op);
13686 const result = switch (try self.isNullPtr(inst, ty, operand)) {13686 const result: MCValue = switch (try self.isNullPtr(inst, ty, operand)) {
13687 .eflags => |cc| .{ .eflags = cc.negate() },13687 .eflags => |cc| .{ .eflags = cc.negate() },
13688 else => unreachable,13688 else => unreachable,
13689 };13689 };
src/codegen.zig+3-3
...@@ -216,7 +216,7 @@ pub fn generateSymbol(...@@ -216,7 +216,7 @@ pub fn generateSymbol(
216 .error_union_type,216 .error_union_type,
217 .simple_type,217 .simple_type,
218 .struct_type,218 .struct_type,
219 .anon_struct_type,219 .tuple_type,
220 .union_type,220 .union_type,
221 .opaque_type,221 .opaque_type,
222 .enum_type,222 .enum_type,
...@@ -230,7 +230,7 @@ pub fn generateSymbol(...@@ -230,7 +230,7 @@ pub fn generateSymbol(
230 .undefined,230 .undefined,
231 .void,231 .void,
232 .null,232 .null,
233 .empty_struct,233 .empty_tuple,
234 .@"unreachable",234 .@"unreachable",
235 .generic_poison,235 .generic_poison,
236 => unreachable, // non-runtime values236 => unreachable, // non-runtime values
...@@ -456,7 +456,7 @@ pub fn generateSymbol(...@@ -456,7 +456,7 @@ pub fn generateSymbol(
456 if (padding > 0) try code.appendNTimes(0, padding);456 if (padding > 0) try code.appendNTimes(0, padding);
457 }457 }
458 },458 },
459 .anon_struct_type => |tuple| {459 .tuple_type => |tuple| {
460 const struct_begin = code.items.len;460 const struct_begin = code.items.len;
461 for (461 for (
462 tuple.types.get(ip),462 tuple.types.get(ip),
src/codegen/c.zig+16-25
...@@ -891,7 +891,7 @@ pub const DeclGen = struct {...@@ -891,7 +891,7 @@ pub const DeclGen = struct {
891 .error_union_type,891 .error_union_type,
892 .simple_type,892 .simple_type,
893 .struct_type,893 .struct_type,
894 .anon_struct_type,894 .tuple_type,
895 .union_type,895 .union_type,
896 .opaque_type,896 .opaque_type,
897 .enum_type,897 .enum_type,
...@@ -908,7 +908,7 @@ pub const DeclGen = struct {...@@ -908,7 +908,7 @@ pub const DeclGen = struct {
908 .undefined => unreachable,908 .undefined => unreachable,
909 .void => unreachable,909 .void => unreachable,
910 .null => unreachable,910 .null => unreachable,
911 .empty_struct => unreachable,911 .empty_tuple => unreachable,
912 .@"unreachable" => unreachable,912 .@"unreachable" => unreachable,
913 .generic_poison => unreachable,913 .generic_poison => unreachable,
914914
...@@ -1194,7 +1194,7 @@ pub const DeclGen = struct {...@@ -1194,7 +1194,7 @@ pub const DeclGen = struct {
1194 try writer.writeByte('}');1194 try writer.writeByte('}');
1195 }1195 }
1196 },1196 },
1197 .anon_struct_type => |tuple| {1197 .tuple_type => |tuple| {
1198 if (!location.isInitializer()) {1198 if (!location.isInitializer()) {
1199 try writer.writeByte('(');1199 try writer.writeByte('(');
1200 try dg.renderCType(writer, ctype);1200 try dg.renderCType(writer, ctype);
...@@ -1605,7 +1605,7 @@ pub const DeclGen = struct {...@@ -1605,7 +1605,7 @@ pub const DeclGen = struct {
1605 }),1605 }),
1606 }1606 }
1607 },1607 },
1608 .anon_struct_type => |anon_struct_info| {1608 .tuple_type => |tuple_info| {
1609 if (!location.isInitializer()) {1609 if (!location.isInitializer()) {
1610 try writer.writeByte('(');1610 try writer.writeByte('(');
1611 try dg.renderCType(writer, ctype);1611 try dg.renderCType(writer, ctype);
...@@ -1614,9 +1614,9 @@ pub const DeclGen = struct {...@@ -1614,9 +1614,9 @@ pub const DeclGen = struct {
16141614
1615 try writer.writeByte('{');1615 try writer.writeByte('{');
1616 var need_comma = false;1616 var need_comma = false;
1617 for (0..anon_struct_info.types.len) |field_index| {1617 for (0..tuple_info.types.len) |field_index| {
1618 if (anon_struct_info.values.get(ip)[field_index] != .none) continue;1618 if (tuple_info.values.get(ip)[field_index] != .none) continue;
1619 const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]);1619 const field_ty = Type.fromInterned(tuple_info.types.get(ip)[field_index]);
1620 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;1620 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
16211621
1622 if (need_comma) try writer.writeByte(',');1622 if (need_comma) try writer.writeByte(',');
...@@ -5411,9 +5411,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5411,9 +5411,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5411 const input_val = try f.resolveInst(input);5411 const input_val = try f.resolveInst(input);
5412 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});5412 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});
5413 try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: {5413 try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: {
5414 const input_local = .{ .local = locals_index };5414 const input_local_idx = locals_index;
5415 locals_index += 1;5415 locals_index += 1;
5416 break :local input_local;5416 break :local .{ .local = input_local_idx };
5417 } else input_val, .Other);5417 } else input_val, .Other);
5418 try writer.writeByte(')');5418 try writer.writeByte(')');
5419 }5419 }
...@@ -5651,15 +5651,12 @@ fn fieldLocation(...@@ -5651,15 +5651,12 @@ fn fieldLocation(
5651 .begin,5651 .begin,
5652 };5652 };
5653 },5653 },
5654 .anon_struct_type => |anon_struct_info| return if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu))5654 .tuple_type => return if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu))
5655 .begin5655 .begin
5656 else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu))5656 else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu))
5657 .{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) }5657 .{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) }
5658 else5658 else
5659 .{ .field = if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name|5659 .{ .field = .{ .field = field_index } },
5660 .{ .identifier = field_name.toSlice(ip) }
5661 else
5662 .{ .field = field_index } },
5663 .union_type => {5660 .union_type => {
5664 const loaded_union = ip.loadUnionType(container_ty.toIntern());5661 const loaded_union = ip.loadUnionType(container_ty.toIntern());
5665 switch (loaded_union.flagsUnordered(ip).layout) {5662 switch (loaded_union.flagsUnordered(ip).layout) {
...@@ -5892,10 +5889,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5892,10 +5889,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5892 },5889 },
5893 }5890 }
5894 },5891 },
5895 .anon_struct_type => |anon_struct_info| if (anon_struct_info.fieldName(ip, extra.field_index).unwrap()) |field_name|5892 .tuple_type => .{ .field = extra.field_index },
5896 .{ .identifier = field_name.toSlice(ip) }
5897 else
5898 .{ .field = extra.field_index },
5899 .union_type => field_name: {5893 .union_type => field_name: {
5900 const loaded_union = ip.loadUnionType(struct_ty.toIntern());5894 const loaded_union = ip.loadUnionType(struct_ty.toIntern());
5901 switch (loaded_union.flagsUnordered(ip).layout) {5895 switch (loaded_union.flagsUnordered(ip).layout) {
...@@ -7366,16 +7360,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7366,16 +7360,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
7366 },7360 },
7367 }7361 }
7368 },7362 },
7369 .anon_struct_type => |anon_struct_info| for (0..anon_struct_info.types.len) |field_index| {7363 .tuple_type => |tuple_info| for (0..tuple_info.types.len) |field_index| {
7370 if (anon_struct_info.values.get(ip)[field_index] != .none) continue;7364 if (tuple_info.values.get(ip)[field_index] != .none) continue;
7371 const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]);7365 const field_ty = Type.fromInterned(tuple_info.types.get(ip)[field_index]);
7372 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;7366 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
73737367
7374 const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));7368 const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete));
7375 try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name|7369 try f.writeCValueMember(writer, local, .{ .field = field_index });
7376 .{ .identifier = field_name.toSlice(ip) }
7377 else
7378 .{ .field = field_index });
7379 try a.assign(f, writer);7370 try a.assign(f, writer);
7380 try f.writeCValue(writer, resolved_elements[field_index], .Other);7371 try f.writeCValue(writer, resolved_elements[field_index], .Other);
7381 try a.end(f, writer);7372 try a.end(f, writer);
src/codegen/c/Type.zig+8-12
...@@ -1350,7 +1350,7 @@ pub const Pool = struct {...@@ -1350,7 +1350,7 @@ pub const Pool = struct {
1350 .i0_type,1350 .i0_type,
1351 .anyopaque_type,1351 .anyopaque_type,
1352 .void_type,1352 .void_type,
1353 .empty_struct_type,1353 .empty_tuple_type,
1354 .type_type,1354 .type_type,
1355 .comptime_int_type,1355 .comptime_int_type,
1356 .comptime_float_type,1356 .comptime_float_type,
...@@ -1450,7 +1450,7 @@ pub const Pool = struct {...@@ -1450,7 +1450,7 @@ pub const Pool = struct {
1450 .null_value,1450 .null_value,
1451 .bool_true,1451 .bool_true,
1452 .bool_false,1452 .bool_false,
1453 .empty_struct,1453 .empty_tuple,
1454 .generic_poison,1454 .generic_poison,
1455 .none,1455 .none,
1456 => unreachable,1456 => unreachable,
...@@ -1730,16 +1730,16 @@ pub const Pool = struct {...@@ -1730,16 +1730,16 @@ pub const Pool = struct {
1730 ),1730 ),
1731 }1731 }
1732 },1732 },
1733 .anon_struct_type => |anon_struct_info| {1733 .tuple_type => |tuple_info| {
1734 const scratch_top = scratch.items.len;1734 const scratch_top = scratch.items.len;
1735 defer scratch.shrinkRetainingCapacity(scratch_top);1735 defer scratch.shrinkRetainingCapacity(scratch_top);
1736 try scratch.ensureUnusedCapacity(allocator, anon_struct_info.types.len *1736 try scratch.ensureUnusedCapacity(allocator, tuple_info.types.len *
1737 @typeInfo(Field).@"struct".fields.len);1737 @typeInfo(Field).@"struct".fields.len);
1738 var hasher = Hasher.init;1738 var hasher = Hasher.init;
1739 for (0..anon_struct_info.types.len) |field_index| {1739 for (0..tuple_info.types.len) |field_index| {
1740 if (anon_struct_info.values.get(ip)[field_index] != .none) continue;1740 if (tuple_info.values.get(ip)[field_index] != .none) continue;
1741 const field_type = Type.fromInterned(1741 const field_type = Type.fromInterned(
1742 anon_struct_info.types.get(ip)[field_index],1742 tuple_info.types.get(ip)[field_index],
1743 );1743 );
1744 const field_ctype = try pool.fromType(1744 const field_ctype = try pool.fromType(
1745 allocator,1745 allocator,
...@@ -1750,11 +1750,7 @@ pub const Pool = struct {...@@ -1750,11 +1750,7 @@ pub const Pool = struct {
1750 kind.noParameter(),1750 kind.noParameter(),
1751 );1751 );
1752 if (field_ctype.index == .void) continue;1752 if (field_ctype.index == .void) continue;
1753 const field_name = if (anon_struct_info.fieldName(ip, @intCast(field_index))1753 const field_name = try pool.fmt(allocator, "f{d}", .{field_index});
1754 .unwrap()) |field_name|
1755 try pool.string(allocator, field_name.toSlice(ip))
1756 else
1757 try pool.fmt(allocator, "f{d}", .{field_index});
1758 pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{1754 pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{
1759 .name = field_name.index,1755 .name = field_name.index,
1760 .ctype = field_ctype.index,1756 .ctype = field_ctype.index,
src/codegen/llvm.zig+14-17
...@@ -2563,7 +2563,7 @@ pub const Object = struct {...@@ -2563,7 +2563,7 @@ pub const Object = struct {
2563 }2563 }
25642564
2565 switch (ip.indexToKey(ty.toIntern())) {2565 switch (ip.indexToKey(ty.toIntern())) {
2566 .anon_struct_type => |tuple| {2566 .tuple_type => |tuple| {
2567 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .empty;2567 var fields: std.ArrayListUnmanaged(Builder.Metadata) = .empty;
2568 defer fields.deinit(gpa);2568 defer fields.deinit(gpa);
25692569
...@@ -2582,11 +2582,8 @@ pub const Object = struct {...@@ -2582,11 +2582,8 @@ pub const Object = struct {
2582 const field_offset = field_align.forward(offset);2582 const field_offset = field_align.forward(offset);
2583 offset = field_offset + field_size;2583 offset = field_offset + field_size;
25842584
2585 const field_name = if (tuple.names.len != 0)2585 var name_buf: [32]u8 = undefined;
2586 tuple.names.get(ip)[i].toSlice(ip)2586 const field_name = std.fmt.bufPrint(&name_buf, "{d}", .{i}) catch unreachable;
2587 else
2588 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2589 defer if (tuple.names.len == 0) gpa.free(field_name);
25902587
2591 fields.appendAssumeCapacity(try o.builder.debugMemberType(2588 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2592 try o.builder.metadataString(field_name),2589 try o.builder.metadataString(field_name),
...@@ -3426,7 +3423,7 @@ pub const Object = struct {...@@ -3426,7 +3423,7 @@ pub const Object = struct {
3426 .adhoc_inferred_error_set_type,3423 .adhoc_inferred_error_set_type,
3427 => try o.errorIntType(),3424 => try o.errorIntType(),
3428 .generic_poison_type,3425 .generic_poison_type,
3429 .empty_struct_type,3426 .empty_tuple_type,
3430 => unreachable,3427 => unreachable,
3431 // values, not types3428 // values, not types
3432 .undef,3429 .undef,
...@@ -3443,7 +3440,7 @@ pub const Object = struct {...@@ -3443,7 +3440,7 @@ pub const Object = struct {
3443 .null_value,3440 .null_value,
3444 .bool_true,3441 .bool_true,
3445 .bool_false,3442 .bool_false,
3446 .empty_struct,3443 .empty_tuple,
3447 .generic_poison,3444 .generic_poison,
3448 .none,3445 .none,
3449 => unreachable,3446 => unreachable,
...@@ -3610,13 +3607,13 @@ pub const Object = struct {...@@ -3610,13 +3607,13 @@ pub const Object = struct {
3610 );3607 );
3611 return ty;3608 return ty;
3612 },3609 },
3613 .anon_struct_type => |anon_struct_type| {3610 .tuple_type => |tuple_type| {
3614 var llvm_field_types: std.ArrayListUnmanaged(Builder.Type) = .empty;3611 var llvm_field_types: std.ArrayListUnmanaged(Builder.Type) = .empty;
3615 defer llvm_field_types.deinit(o.gpa);3612 defer llvm_field_types.deinit(o.gpa);
3616 // Although we can estimate how much capacity to add, these cannot be3613 // Although we can estimate how much capacity to add, these cannot be
3617 // relied upon because of the recursive calls to lowerType below.3614 // relied upon because of the recursive calls to lowerType below.
3618 try llvm_field_types.ensureUnusedCapacity(o.gpa, anon_struct_type.types.len);3615 try llvm_field_types.ensureUnusedCapacity(o.gpa, tuple_type.types.len);
3619 try o.struct_field_map.ensureUnusedCapacity(o.gpa, anon_struct_type.types.len);3616 try o.struct_field_map.ensureUnusedCapacity(o.gpa, tuple_type.types.len);
36203617
3621 comptime assert(struct_layout_version == 2);3618 comptime assert(struct_layout_version == 2);
3622 var offset: u64 = 0;3619 var offset: u64 = 0;
...@@ -3625,8 +3622,8 @@ pub const Object = struct {...@@ -3625,8 +3622,8 @@ pub const Object = struct {
3625 const struct_size = t.abiSize(zcu);3622 const struct_size = t.abiSize(zcu);
36263623
3627 for (3624 for (
3628 anon_struct_type.types.get(ip),3625 tuple_type.types.get(ip),
3629 anon_struct_type.values.get(ip),3626 tuple_type.values.get(ip),
3630 0..,3627 0..,
3631 ) |field_ty, field_val, field_index| {3628 ) |field_ty, field_val, field_index| {
3632 if (field_val != .none) continue;3629 if (field_val != .none) continue;
...@@ -3979,7 +3976,7 @@ pub const Object = struct {...@@ -3979,7 +3976,7 @@ pub const Object = struct {
3979 .error_union_type,3976 .error_union_type,
3980 .simple_type,3977 .simple_type,
3981 .struct_type,3978 .struct_type,
3982 .anon_struct_type,3979 .tuple_type,
3983 .union_type,3980 .union_type,
3984 .opaque_type,3981 .opaque_type,
3985 .enum_type,3982 .enum_type,
...@@ -3993,7 +3990,7 @@ pub const Object = struct {...@@ -3993,7 +3990,7 @@ pub const Object = struct {
3993 .undefined => unreachable, // non-runtime value3990 .undefined => unreachable, // non-runtime value
3994 .void => unreachable, // non-runtime value3991 .void => unreachable, // non-runtime value
3995 .null => unreachable, // non-runtime value3992 .null => unreachable, // non-runtime value
3996 .empty_struct => unreachable, // non-runtime value3993 .empty_tuple => unreachable, // non-runtime value
3997 .@"unreachable" => unreachable, // non-runtime value3994 .@"unreachable" => unreachable, // non-runtime value
3998 .generic_poison => unreachable, // non-runtime value3995 .generic_poison => unreachable, // non-runtime value
39993996
...@@ -4232,7 +4229,7 @@ pub const Object = struct {...@@ -4232,7 +4229,7 @@ pub const Object = struct {
4232 ),4229 ),
4233 }4230 }
4234 },4231 },
4235 .anon_struct_type => |tuple| {4232 .tuple_type => |tuple| {
4236 const struct_ty = try o.lowerType(ty);4233 const struct_ty = try o.lowerType(ty);
4237 const llvm_len = struct_ty.aggregateLen(&o.builder);4234 const llvm_len = struct_ty.aggregateLen(&o.builder);
42384235
...@@ -12516,7 +12513,7 @@ fn isByRef(ty: Type, zcu: *Zcu) bool {...@@ -12516,7 +12513,7 @@ fn isByRef(ty: Type, zcu: *Zcu) bool {
12516 .array, .frame => return ty.hasRuntimeBits(zcu),12513 .array, .frame => return ty.hasRuntimeBits(zcu),
12517 .@"struct" => {12514 .@"struct" => {
12518 const struct_type = switch (ip.indexToKey(ty.toIntern())) {12515 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
12519 .anon_struct_type => |tuple| {12516 .tuple_type => |tuple| {
12520 var count: usize = 0;12517 var count: usize = 0;
12521 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| {12518 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| {
12522 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;12519 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
src/codegen/spirv.zig+32-31
...@@ -731,13 +731,15 @@ const NavGen = struct {...@@ -731,13 +731,15 @@ const NavGen = struct {
731 .direct => {731 .direct => {
732 const result_ty_id = try self.resolveType(Type.bool, .direct);732 const result_ty_id = try self.resolveType(Type.bool, .direct);
733 const result_id = self.spv.allocId();733 const result_id = self.spv.allocId();
734 const operands = .{
735 .id_result_type = result_ty_id,
736 .id_result = result_id,
737 };
738 switch (value) {734 switch (value) {
739 true => try section.emit(self.spv.gpa, .OpConstantTrue, operands),735 inline else => |val_ct| try section.emit(
740 false => try section.emit(self.spv.gpa, .OpConstantFalse, operands),736 self.spv.gpa,
737 if (val_ct) .OpConstantTrue else .OpConstantFalse,
738 .{
739 .id_result_type = result_ty_id,
740 .id_result = result_id,
741 },
742 ),
741 }743 }
742 return result_id;744 return result_id;
743 },745 },
...@@ -915,7 +917,7 @@ const NavGen = struct {...@@ -915,7 +917,7 @@ const NavGen = struct {
915 .error_union_type,917 .error_union_type,
916 .simple_type,918 .simple_type,
917 .struct_type,919 .struct_type,
918 .anon_struct_type,920 .tuple_type,
919 .union_type,921 .union_type,
920 .opaque_type,922 .opaque_type,
921 .enum_type,923 .enum_type,
...@@ -937,7 +939,7 @@ const NavGen = struct {...@@ -937,7 +939,7 @@ const NavGen = struct {
937 .undefined,939 .undefined,
938 .void,940 .void,
939 .null,941 .null,
940 .empty_struct,942 .empty_tuple,
941 .@"unreachable",943 .@"unreachable",
942 .generic_poison,944 .generic_poison,
943 => unreachable, // non-runtime values945 => unreachable, // non-runtime values
...@@ -1125,7 +1127,7 @@ const NavGen = struct {...@@ -1125,7 +1127,7 @@ const NavGen = struct {
11251127
1126 return try self.constructStruct(ty, types.items, constituents.items);1128 return try self.constructStruct(ty, types.items, constituents.items);
1127 },1129 },
1128 .anon_struct_type => unreachable, // TODO1130 .tuple_type => unreachable, // TODO
1129 else => unreachable,1131 else => unreachable,
1130 },1132 },
1131 .un => |un| {1133 .un => |un| {
...@@ -1718,7 +1720,7 @@ const NavGen = struct {...@@ -1718,7 +1720,7 @@ const NavGen = struct {
1718 },1720 },
1719 .@"struct" => {1721 .@"struct" => {
1720 const struct_type = switch (ip.indexToKey(ty.toIntern())) {1722 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
1721 .anon_struct_type => |tuple| {1723 .tuple_type => |tuple| {
1722 const member_types = try self.gpa.alloc(IdRef, tuple.values.len);1724 const member_types = try self.gpa.alloc(IdRef, tuple.values.len);
1723 defer self.gpa.free(member_types);1725 defer self.gpa.free(member_types);
17241726
...@@ -2831,18 +2833,12 @@ const NavGen = struct {...@@ -2831,18 +2833,12 @@ const NavGen = struct {
2831 }2833 }
2832 },2834 },
2833 .vulkan => {2835 .vulkan => {
2834 const op_result_ty = blk: {2836 // Operations return a struct{T, T}
2835 // Operations return a struct{T, T}2837 // where T is maybe vectorized.
2836 // where T is maybe vectorized.2838 const op_result_ty: Type = .fromInterned(try ip.getTupleType(zcu.gpa, pt.tid, .{
2837 const types = [2]InternPool.Index{ arith_op_ty.toIntern(), arith_op_ty.toIntern() };2839 .types = &.{ arith_op_ty.toIntern(), arith_op_ty.toIntern() },
2838 const values = [2]InternPool.Index{ .none, .none };2840 .values = &.{ .none, .none },
2839 const index = try ip.getAnonStructType(zcu.gpa, pt.tid, .{2841 }));
2840 .types = &types,
2841 .values = &values,
2842 .names = &.{},
2843 });
2844 break :blk Type.fromInterned(index);
2845 };
2846 const op_result_ty_id = try self.resolveType(op_result_ty, .direct);2842 const op_result_ty_id = try self.resolveType(op_result_ty, .direct);
28472843
2848 const opcode: Opcode = switch (op) {2844 const opcode: Opcode = switch (op) {
...@@ -4867,7 +4863,7 @@ const NavGen = struct {...@@ -4867,7 +4863,7 @@ const NavGen = struct {
4867 var index: usize = 0;4863 var index: usize = 0;
48684864
4869 switch (ip.indexToKey(result_ty.toIntern())) {4865 switch (ip.indexToKey(result_ty.toIntern())) {
4870 .anon_struct_type => |tuple| {4866 .tuple_type => |tuple| {
4871 for (tuple.types.get(ip), elements, 0..) |field_ty, element, i| {4867 for (tuple.types.get(ip), elements, 0..) |field_ty, element, i| {
4872 if ((try result_ty.structFieldValueComptime(pt, i)) != null) continue;4868 if ((try result_ty.structFieldValueComptime(pt, i)) != null) continue;
4873 assert(Type.fromInterned(field_ty).hasRuntimeBits(zcu));4869 assert(Type.fromInterned(field_ty).hasRuntimeBits(zcu));
...@@ -6216,15 +6212,20 @@ const NavGen = struct {...@@ -6216,15 +6212,20 @@ const NavGen = struct {
6216 try self.extractField(Type.anyerror, operand_id, eu_layout.errorFieldIndex());6212 try self.extractField(Type.anyerror, operand_id, eu_layout.errorFieldIndex());
62176213
6218 const result_id = self.spv.allocId();6214 const result_id = self.spv.allocId();
6219 const operands = .{
6220 .id_result_type = bool_ty_id,
6221 .id_result = result_id,
6222 .operand_1 = error_id,
6223 .operand_2 = try self.constInt(Type.anyerror, 0, .direct),
6224 };
6225 switch (pred) {6215 switch (pred) {
6226 .is_err => try self.func.body.emit(self.spv.gpa, .OpINotEqual, operands),6216 inline else => |pred_ct| try self.func.body.emit(
6227 .is_non_err => try self.func.body.emit(self.spv.gpa, .OpIEqual, operands),6217 self.spv.gpa,
6218 switch (pred_ct) {
6219 .is_err => .OpINotEqual,
6220 .is_non_err => .OpIEqual,
6221 },
6222 .{
6223 .id_result_type = bool_ty_id,
6224 .id_result = result_id,
6225 .operand_1 = error_id,
6226 .operand_2 = try self.constInt(Type.anyerror, 0, .direct),
6227 },
6228 ),
6228 }6229 }
6229 return result_id;6230 return result_id;
6230 }6231 }
src/link/Dwarf.zig+29-20
...@@ -2599,16 +2599,15 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2599,16 +2599,15 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2599 .anyframe_type,2599 .anyframe_type,
2600 .error_union_type,2600 .error_union_type,
2601 .simple_type,2601 .simple_type,
2602 .anon_struct_type,2602 .tuple_type,
2603 .func_type,2603 .func_type,
2604 .error_set_type,2604 .error_set_type,
2605 .inferred_error_set_type,2605 .inferred_error_set_type,
2606 => .decl_alias,2606 => .decl_alias,
2607 .struct_type => tag: {2607 .struct_type => tag: {
2608 const loaded_struct = ip.loadStructType(nav_val.toIntern());2608 const loaded_struct = ip.loadStructType(nav_val.toIntern());
2609 if (loaded_struct.zir_index == .none) break :tag .decl_alias;
26102609
2611 const type_inst_info = loaded_struct.zir_index.unwrap().?.resolveFull(ip).?;2610 const type_inst_info = loaded_struct.zir_index.resolveFull(ip).?;
2612 if (type_inst_info.file != inst_info.file) break :tag .decl_alias;2611 if (type_inst_info.file != inst_info.file) break :tag .decl_alias;
26132612
2614 const value_inst = value_inst: {2613 const value_inst = value_inst: {
...@@ -3349,7 +3348,7 @@ fn updateType(...@@ -3349,7 +3348,7 @@ fn updateType(
3349 .union_type,3348 .union_type,
3350 .opaque_type,3349 .opaque_type,
3351 => unreachable,3350 => unreachable,
3352 .anon_struct_type => |anon_struct_type| if (anon_struct_type.types.len == 0) {3351 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {
3353 try wip_nav.abbrevCode(.namespace_struct_type);3352 try wip_nav.abbrevCode(.namespace_struct_type);
3354 try wip_nav.strp(name);3353 try wip_nav.strp(name);
3355 try diw.writeByte(@intFromBool(false));3354 try diw.writeByte(@intFromBool(false));
...@@ -3359,15 +3358,15 @@ fn updateType(...@@ -3359,15 +3358,15 @@ fn updateType(
3359 try uleb128(diw, ty.abiSize(zcu));3358 try uleb128(diw, ty.abiSize(zcu));
3360 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);3359 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);
3361 var field_byte_offset: u64 = 0;3360 var field_byte_offset: u64 = 0;
3362 for (0..anon_struct_type.types.len) |field_index| {3361 for (0..tuple_type.types.len) |field_index| {
3363 const comptime_value = anon_struct_type.values.get(ip)[field_index];3362 const comptime_value = tuple_type.values.get(ip)[field_index];
3364 try wip_nav.abbrevCode(if (comptime_value != .none) .struct_field_comptime else .struct_field);3363 try wip_nav.abbrevCode(if (comptime_value != .none) .struct_field_comptime else .struct_field);
3365 if (anon_struct_type.fieldName(ip, field_index).unwrap()) |field_name| try wip_nav.strp(field_name.toSlice(ip)) else {3364 {
3366 const field_name = try std.fmt.allocPrint(dwarf.gpa, "{d}", .{field_index});3365 var name_buf: [32]u8 = undefined;
3367 defer dwarf.gpa.free(field_name);3366 const field_name = std.fmt.bufPrint(&name_buf, "{d}", .{field_index}) catch unreachable;
3368 try wip_nav.strp(field_name);3367 try wip_nav.strp(field_name);
3369 }3368 }
3370 const field_type = Type.fromInterned(anon_struct_type.types.get(ip)[field_index]);3369 const field_type = Type.fromInterned(tuple_type.types.get(ip)[field_index]);
3371 try wip_nav.refType(field_type);3370 try wip_nav.refType(field_type);
3372 if (comptime_value != .none) try wip_nav.blockValue(3371 if (comptime_value != .none) try wip_nav.blockValue(
3373 src_loc,3372 src_loc,
...@@ -3595,16 +3594,26 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP...@@ -3595,16 +3594,26 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
3595 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);3594 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);
3596 try wip_nav.flush(ty_src_loc);3595 try wip_nav.flush(ty_src_loc);
3597 } else {3596 } else {
3598 const decl_inst = file.zir.instructions.get(@intFromEnum(inst_info.inst));3597 {
3599 assert(decl_inst.tag == .extended);3598 // Note that changes to ZIR instruction tracking only need to update this code
3600 if (switch (decl_inst.data.extended.opcode) {3599 // if a newly-tracked instruction can be a type's owner `zir_index`.
3601 .struct_decl => @as(Zir.Inst.StructDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,3600 comptime assert(Zir.inst_tracking_version == 0);
3602 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,3601
3603 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,3602 const decl_inst = file.zir.instructions.get(@intFromEnum(inst_info.inst));
3604 .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,3603 const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) {
3605 .reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)),3604 .struct_init, .struct_init_ref, .struct_init_anon => .anon,
3606 else => unreachable,3605 .extended => switch (decl_inst.data.extended.opcode) {
3607 } == .parent) return;3606 .struct_decl => @as(Zir.Inst.StructDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
3607 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
3608 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
3609 .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
3610 .reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)),
3611 else => unreachable,
3612 },
3613 else => unreachable,
3614 };
3615 if (name_strat == .parent) return;
3616 }
36083617
3609 const unit = try dwarf.getUnit(file.mod);3618 const unit = try dwarf.getUnit(file.mod);
3610 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index);3619 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index);
src/link/Plan9.zig+1-1
...@@ -931,7 +931,7 @@ fn addNavExports(...@@ -931,7 +931,7 @@ fn addNavExports(
931 break;931 break;
932 }932 }
933 }933 }
934 const sym = .{934 const sym: aout.Sym = .{
935 .value = atom.offset.?,935 .value = atom.offset.?,
936 .type = atom.type.toGlobal(),936 .type = atom.type.toGlobal(),
937 .name = try gpa.dupe(u8, exp_name),937 .name = try gpa.dupe(u8, exp_name),
src/main.zig+1-1
...@@ -34,7 +34,7 @@ const Zcu = @import("Zcu.zig");...@@ -34,7 +34,7 @@ const Zcu = @import("Zcu.zig");
34const mingw = @import("mingw.zig");34const mingw = @import("mingw.zig");
35const dev = @import("dev.zig");35const dev = @import("dev.zig");
3636
37pub const std_options = .{37pub const std_options: std.Options = .{
38 .wasiCwd = wasi_cwd,38 .wasiCwd = wasi_cwd,
39 .logFn = log,39 .logFn = log,
40 .enable_segfault_handler = false,40 .enable_segfault_handler = false,
src/print_value.zig+2-2
...@@ -74,7 +74,7 @@ pub fn print(...@@ -74,7 +74,7 @@ pub fn print(
74 .error_union_type,74 .error_union_type,
75 .simple_type,75 .simple_type,
76 .struct_type,76 .struct_type,
77 .anon_struct_type,77 .tuple_type,
78 .union_type,78 .union_type,
79 .opaque_type,79 .opaque_type,
80 .enum_type,80 .enum_type,
...@@ -85,7 +85,7 @@ pub fn print(...@@ -85,7 +85,7 @@ pub fn print(
85 .undef => try writer.writeAll("undefined"),85 .undef => try writer.writeAll("undefined"),
86 .simple_value => |simple_value| switch (simple_value) {86 .simple_value => |simple_value| switch (simple_value) {
87 .void => try writer.writeAll("{}"),87 .void => try writer.writeAll("{}"),
88 .empty_struct => try writer.writeAll(".{}"),88 .empty_tuple => try writer.writeAll(".{}"),
89 .generic_poison => try writer.writeAll("(generic poison)"),89 .generic_poison => try writer.writeAll("(generic poison)"),
90 else => try writer.writeAll(@tagName(simple_value)),90 else => try writer.writeAll(@tagName(simple_value)),
91 },91 },
src/print_zir.zig+30-6
...@@ -563,6 +563,8 @@ const Writer = struct {...@@ -563,6 +563,8 @@ const Writer = struct {
563 .enum_decl => try self.writeEnumDecl(stream, extended),563 .enum_decl => try self.writeEnumDecl(stream, extended),
564 .opaque_decl => try self.writeOpaqueDecl(stream, extended),564 .opaque_decl => try self.writeOpaqueDecl(stream, extended),
565565
566 .tuple_decl => try self.writeTupleDecl(stream, extended),
567
566 .await_nosuspend,568 .await_nosuspend,
567 .c_undef,569 .c_undef,
568 .c_include,570 .c_include,
...@@ -1421,7 +1423,6 @@ const Writer = struct {...@@ -1421,7 +1423,6 @@ const Writer = struct {
14211423
1422 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);1424 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
1423 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);1425 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
1424 try self.writeFlag(stream, "tuple, ", small.is_tuple);
14251426
1426 try stream.print("{s}, ", .{@tagName(small.name_strategy)});1427 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
14271428
...@@ -1506,11 +1507,8 @@ const Writer = struct {...@@ -1506,11 +1507,8 @@ const Writer = struct {
1506 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;1507 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
1507 cur_bit_bag >>= 1;1508 cur_bit_bag >>= 1;
15081509
1509 var field_name_index: Zir.NullTerminatedString = .empty;1510 const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1510 if (!small.is_tuple) {1511 extra_index += 1;
1511 field_name_index = @enumFromInt(self.code.extra[extra_index]);
1512 extra_index += 1;
1513 }
1514 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);1512 const doc_comment_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]);
1515 extra_index += 1;1513 extra_index += 1;
15161514
...@@ -1948,6 +1946,32 @@ const Writer = struct {...@@ -1948,6 +1946,32 @@ const Writer = struct {
1948 try self.writeSrcNode(stream, 0);1946 try self.writeSrcNode(stream, 0);
1949 }1947 }
19501948
1949 fn writeTupleDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
1950 const fields_len = extended.small;
1951 assert(fields_len != 0);
1952 const extra = self.code.extraData(Zir.Inst.TupleDecl, extended.operand);
1953
1954 var extra_index = extra.end;
1955
1956 try stream.writeAll("{ ");
1957
1958 for (0..fields_len) |field_idx| {
1959 if (field_idx != 0) try stream.writeAll(", ");
1960
1961 const field_ty, const field_init = self.code.extra[extra_index..][0..2].*;
1962 extra_index += 2;
1963
1964 try stream.print("@\"{d}\": ", .{field_idx});
1965 try self.writeInstRef(stream, @enumFromInt(field_ty));
1966 try stream.writeAll(" = ");
1967 try self.writeInstRef(stream, @enumFromInt(field_init));
1968 }
1969
1970 try stream.writeAll(" }) ");
1971
1972 try self.writeSrcNode(stream, extra.data.src_node);
1973 }
1974
1951 fn writeErrorSetDecl(1975 fn writeErrorSetDecl(
1952 self: *Writer,1976 self: *Writer,
1953 stream: anytype,1977 stream: anytype,
src/translate_c.zig+8-5
...@@ -2314,8 +2314,11 @@ fn transStringLiteralInitializer(...@@ -2314,8 +2314,11 @@ fn transStringLiteralInitializer(
2314 while (i < num_inits) : (i += 1) {2314 while (i < num_inits) : (i += 1) {
2315 init_list[i] = try transCreateCharLitNode(c, false, stmt.getCodeUnit(i));2315 init_list[i] = try transCreateCharLitNode(c, false, stmt.getCodeUnit(i));
2316 }2316 }
2317 const init_args = .{ .len = num_inits, .elem_type = elem_type };2317 const init_args: ast.Payload.Array.ArrayTypeInfo = .{ .len = num_inits, .elem_type = elem_type };
2318 const init_array_type = try if (array_type.tag() == .array_type) Tag.array_type.create(c.arena, init_args) else Tag.null_sentinel_array_type.create(c.arena, init_args);2318 const init_array_type = if (array_type.tag() == .array_type)
2319 try Tag.array_type.create(c.arena, init_args)
2320 else
2321 try Tag.null_sentinel_array_type.create(c.arena, init_args);
2319 break :blk try Tag.array_init.create(c.arena, .{2322 break :blk try Tag.array_init.create(c.arena, .{
2320 .cond = init_array_type,2323 .cond = init_array_type,
2321 .cases = init_list,2324 .cases = init_list,
...@@ -3910,7 +3913,7 @@ fn transCreateCompoundAssign(...@@ -3910,7 +3913,7 @@ fn transCreateCompoundAssign(
39103913
3911 if ((is_mod or is_div) and is_signed) {3914 if ((is_mod or is_div) and is_signed) {
3912 if (requires_cast) rhs_node = try transCCast(c, scope, loc, lhs_qt, rhs_qt, rhs_node);3915 if (requires_cast) rhs_node = try transCCast(c, scope, loc, lhs_qt, rhs_qt, rhs_node);
3913 const operands = .{ .lhs = lhs_node, .rhs = rhs_node };3916 const operands: @FieldType(ast.Payload.BinOp, "data") = .{ .lhs = lhs_node, .rhs = rhs_node };
3914 const builtin = if (is_mod)3917 const builtin = if (is_mod)
3915 try Tag.signed_remainder.create(c.arena, operands)3918 try Tag.signed_remainder.create(c.arena, operands)
3916 else3919 else
...@@ -3949,7 +3952,7 @@ fn transCreateCompoundAssign(...@@ -3949,7 +3952,7 @@ fn transCreateCompoundAssign(
3949 if (is_ptr_op_signed) rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);3952 if (is_ptr_op_signed) rhs_node = try usizeCastForWrappingPtrArithmetic(c.arena, rhs_node);
3950 if ((is_mod or is_div) and is_signed) {3953 if ((is_mod or is_div) and is_signed) {
3951 if (requires_cast) rhs_node = try transCCast(c, scope, loc, lhs_qt, rhs_qt, rhs_node);3954 if (requires_cast) rhs_node = try transCCast(c, scope, loc, lhs_qt, rhs_qt, rhs_node);
3952 const operands = .{ .lhs = ref_node, .rhs = rhs_node };3955 const operands: @FieldType(ast.Payload.BinOp, "data") = .{ .lhs = ref_node, .rhs = rhs_node };
3953 const builtin = if (is_mod)3956 const builtin = if (is_mod)
3954 try Tag.signed_remainder.create(c.arena, operands)3957 try Tag.signed_remainder.create(c.arena, operands)
3955 else3958 else
...@@ -4777,7 +4780,7 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan...@@ -4777,7 +4780,7 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan
4777 const is_const = is_fn_proto or child_qt.isConstQualified();4780 const is_const = is_fn_proto or child_qt.isConstQualified();
4778 const is_volatile = child_qt.isVolatileQualified();4781 const is_volatile = child_qt.isVolatileQualified();
4779 const elem_type = try transQualType(c, scope, child_qt, source_loc);4782 const elem_type = try transQualType(c, scope, child_qt, source_loc);
4780 const ptr_info = .{4783 const ptr_info: @FieldType(ast.Payload.Pointer, "data") = .{
4781 .is_const = is_const,4784 .is_const = is_const,
4782 .is_volatile = is_volatile,4785 .is_volatile = is_volatile,
4783 .elem_type = elem_type,4786 .elem_type = elem_type,
test/behavior.zig-1
...@@ -26,7 +26,6 @@ test {...@@ -26,7 +26,6 @@ test {
26 _ = @import("behavior/duplicated_test_names.zig");26 _ = @import("behavior/duplicated_test_names.zig");
27 _ = @import("behavior/defer.zig");27 _ = @import("behavior/defer.zig");
28 _ = @import("behavior/destructure.zig");28 _ = @import("behavior/destructure.zig");
29 _ = @import("behavior/empty_tuple_fields.zig");
30 _ = @import("behavior/empty_union.zig");29 _ = @import("behavior/empty_union.zig");
31 _ = @import("behavior/enum.zig");30 _ = @import("behavior/enum.zig");
32 _ = @import("behavior/error.zig");31 _ = @import("behavior/error.zig");
test/behavior/array.zig+1-35
...@@ -596,7 +596,7 @@ test "type coercion of anon struct literal to array" {...@@ -596,7 +596,7 @@ test "type coercion of anon struct literal to array" {
596596
597 var x2: U = .{ .a = 42 };597 var x2: U = .{ .a = 42 };
598 _ = &x2;598 _ = &x2;
599 const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };599 const t2 = .{ x2, U{ .b = true }, U{ .c = "hello" } };
600 const arr2: [3]U = t2;600 const arr2: [3]U = t2;
601 try expect(arr2[0].a == 42);601 try expect(arr2[0].a == 42);
602 try expect(arr2[1].b == true);602 try expect(arr2[1].b == true);
...@@ -607,40 +607,6 @@ test "type coercion of anon struct literal to array" {...@@ -607,40 +607,6 @@ test "type coercion of anon struct literal to array" {
607 try comptime S.doTheTest();607 try comptime S.doTheTest();
608}608}
609609
610test "type coercion of pointer to anon struct literal to pointer to array" {
611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
612 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
613 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
614
615 const S = struct {
616 const U = union {
617 a: u32,
618 b: bool,
619 c: []const u8,
620 };
621
622 fn doTheTest() !void {
623 var x1: u8 = 42;
624 _ = &x1;
625 const t1 = &.{ x1, 56, 54 };
626 const arr1: *const [3]u8 = t1;
627 try expect(arr1[0] == 42);
628 try expect(arr1[1] == 56);
629 try expect(arr1[2] == 54);
630
631 var x2: U = .{ .a = 42 };
632 _ = &x2;
633 const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } };
634 const arr2: *const [3]U = t2;
635 try expect(arr2[0].a == 42);
636 try expect(arr2[1].b == true);
637 try expect(mem.eql(u8, arr2[2].c, "hello"));
638 }
639 };
640 try S.doTheTest();
641 try comptime S.doTheTest();
642}
643
644test "array with comptime-only element type" {610test "array with comptime-only element type" {
645 const a = [_]type{ u32, i32 };611 const a = [_]type{ u32, i32 };
646 try testing.expect(a[0] == u32);612 try testing.expect(a[0] == u32);
test/behavior/cast.zig-26
...@@ -2600,32 +2600,6 @@ test "result type is preserved into comptime block" {...@@ -2600,32 +2600,6 @@ test "result type is preserved into comptime block" {
2600 try expect(x == 123);2600 try expect(x == 123);
2601}2601}
26022602
2603test "implicit cast from ptr to tuple to ptr to struct" {
2604 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
2605 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2606 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2607 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2608
2609 const ComptimeReason = union(enum) {
2610 c_import: struct {
2611 a: u32,
2612 },
2613 };
2614
2615 const Block = struct {
2616 reason: ?*const ComptimeReason,
2617 };
2618
2619 var a: u32 = 16;
2620 _ = &a;
2621 var reason = .{ .c_import = .{ .a = a } };
2622 var block = Block{
2623 .reason = &reason,
2624 };
2625 _ = &block;
2626 try expect(block.reason.?.c_import.a == 16);
2627}
2628
2629test "bitcast vector" {2603test "bitcast vector" {
2630 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO2604 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
2631 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2605 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/empty_file_level_struct.zig deleted-1
...@@ -1 +0,0 @@
1struct {}
test/behavior/empty_file_level_union.zig deleted-1
...@@ -1 +0,0 @@
1union {}
test/behavior/empty_tuple_fields.zig deleted-28
...@@ -1,28 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4test "empty file level struct" {
5 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
9
10 const T = @import("empty_file_level_struct.zig");
11 const info = @typeInfo(T);
12 try std.testing.expectEqual(@as(usize, 1), info.@"struct".fields.len);
13 try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name);
14 try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"struct");
15}
16
17test "empty file level union" {
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
22
23 const T = @import("empty_file_level_union.zig");
24 const info = @typeInfo(T);
25 try std.testing.expectEqual(@as(usize, 1), info.@"struct".fields.len);
26 try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name);
27 try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"union");
28}
test/behavior/struct.zig+17-78
...@@ -1013,84 +1013,6 @@ test "struct with 0-length union array field" {...@@ -1013,84 +1013,6 @@ test "struct with 0-length union array field" {
1013 try expectEqual(@as(usize, 0), s.zero_length.len);1013 try expectEqual(@as(usize, 0), s.zero_length.len);
1014}1014}
10151015
1016test "type coercion of anon struct literal to struct" {
1017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1018 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1019 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1020 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1021
1022 const S = struct {
1023 const S2 = struct {
1024 A: u32,
1025 B: []const u8,
1026 C: void,
1027 D: Foo = .{},
1028 };
1029
1030 const Foo = struct {
1031 field: i32 = 1234,
1032 };
1033
1034 fn doTheTest() !void {
1035 var y: u32 = 42;
1036 _ = &y;
1037 const t0 = .{ .A = 123, .B = "foo", .C = {} };
1038 const t1 = .{ .A = y, .B = "foo", .C = {} };
1039 const y0: S2 = t0;
1040 const y1: S2 = t1;
1041 try expect(y0.A == 123);
1042 try expect(std.mem.eql(u8, y0.B, "foo"));
1043 try expect(y0.C == {});
1044 try expect(y0.D.field == 1234);
1045 try expect(y1.A == y);
1046 try expect(std.mem.eql(u8, y1.B, "foo"));
1047 try expect(y1.C == {});
1048 try expect(y1.D.field == 1234);
1049 }
1050 };
1051 try S.doTheTest();
1052 try comptime S.doTheTest();
1053}
1054
1055test "type coercion of pointer to anon struct literal to pointer to struct" {
1056 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1057 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1058 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1059 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1060
1061 const S = struct {
1062 const S2 = struct {
1063 A: u32,
1064 B: []const u8,
1065 C: void,
1066 D: Foo = .{},
1067 };
1068
1069 const Foo = struct {
1070 field: i32 = 1234,
1071 };
1072
1073 fn doTheTest() !void {
1074 var y: u32 = 42;
1075 _ = &y;
1076 const t0 = &.{ .A = 123, .B = "foo", .C = {} };
1077 const t1 = &.{ .A = y, .B = "foo", .C = {} };
1078 const y0: *const S2 = t0;
1079 const y1: *const S2 = t1;
1080 try expect(y0.A == 123);
1081 try expect(std.mem.eql(u8, y0.B, "foo"));
1082 try expect(y0.C == {});
1083 try expect(y0.D.field == 1234);
1084 try expect(y1.A == y);
1085 try expect(std.mem.eql(u8, y1.B, "foo"));
1086 try expect(y1.C == {});
1087 try expect(y1.D.field == 1234);
1088 }
1089 };
1090 try S.doTheTest();
1091 try comptime S.doTheTest();
1092}
1093
1094test "packed struct with undefined initializers" {1016test "packed struct with undefined initializers" {
1095 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1017 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1096 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1018 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -2183,3 +2105,20 @@ test "extern struct @FieldType" {...@@ -2183,3 +2105,20 @@ test "extern struct @FieldType" {
2183 comptime assert(@FieldType(S, "b") == f64);2105 comptime assert(@FieldType(S, "b") == f64);
2184 comptime assert(@FieldType(S, "c") == *S);2106 comptime assert(@FieldType(S, "c") == *S);
2185}2107}
2108
2109test "anonymous struct equivalence" {
2110 const S = struct {
2111 fn anonStructType(comptime x: anytype) type {
2112 const val = .{ .a = "hello", .b = x };
2113 return @TypeOf(val);
2114 }
2115 };
2116
2117 const A = S.anonStructType(123);
2118 const B = S.anonStructType(123);
2119 const C = S.anonStructType(456);
2120
2121 comptime assert(A == B);
2122 comptime assert(A != C);
2123 comptime assert(B != C);
2124}
test/behavior/tuple.zig+23-11
...@@ -150,7 +150,7 @@ test "array-like initializer for tuple types" {...@@ -150,7 +150,7 @@ test "array-like initializer for tuple types" {
150 .type = u8,150 .type = u8,
151 .default_value = null,151 .default_value = null,
152 .is_comptime = false,152 .is_comptime = false,
153 .alignment = @alignOf(i32),153 .alignment = @alignOf(u8),
154 },154 },
155 },155 },
156 },156 },
...@@ -566,16 +566,28 @@ test "comptime fields in tuple can be initialized" {...@@ -566,16 +566,28 @@ test "comptime fields in tuple can be initialized" {
566 _ = &a;566 _ = &a;
567}567}
568568
569test "tuple default values" {569test "empty struct in tuple" {
570 const T = struct {570 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
571 usize,571 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
572 usize = 123,572 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
573 usize = 456,573 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
574 };
575574
576 const t: T = .{1};575 const T = struct { struct {} };
576 const info = @typeInfo(T);
577 try std.testing.expectEqual(@as(usize, 1), info.@"struct".fields.len);
578 try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name);
579 try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"struct");
580}
581
582test "empty union in tuple" {
583 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
586 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
577587
578 try expectEqual(1, t[0]);588 const T = struct { union {} };
579 try expectEqual(123, t[1]);589 const info = @typeInfo(T);
580 try expectEqual(456, t[2]);590 try std.testing.expectEqual(@as(usize, 1), info.@"struct".fields.len);
591 try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name);
592 try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"union");
581}593}
test/behavior/tuple_declarations.zig+3-3
...@@ -9,7 +9,7 @@ test "tuple declaration type info" {...@@ -9,7 +9,7 @@ test "tuple declaration type info" {
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1010
11 {11 {
12 const T = struct { comptime u32 align(2) = 1, []const u8 };12 const T = struct { comptime u32 = 1, []const u8 };
13 const info = @typeInfo(T).@"struct";13 const info = @typeInfo(T).@"struct";
1414
15 try expect(info.layout == .auto);15 try expect(info.layout == .auto);
...@@ -22,7 +22,7 @@ test "tuple declaration type info" {...@@ -22,7 +22,7 @@ test "tuple declaration type info" {
22 try expect(info.fields[0].type == u32);22 try expect(info.fields[0].type == u32);
23 try expect(@as(*const u32, @ptrCast(@alignCast(info.fields[0].default_value))).* == 1);23 try expect(@as(*const u32, @ptrCast(@alignCast(info.fields[0].default_value))).* == 1);
24 try expect(info.fields[0].is_comptime);24 try expect(info.fields[0].is_comptime);
25 try expect(info.fields[0].alignment == 2);25 try expect(info.fields[0].alignment == @alignOf(u32));
2626
27 try expectEqualStrings(info.fields[1].name, "1");27 try expectEqualStrings(info.fields[1].name, "1");
28 try expect(info.fields[1].type == []const u8);28 try expect(info.fields[1].type == []const u8);
...@@ -32,7 +32,7 @@ test "tuple declaration type info" {...@@ -32,7 +32,7 @@ test "tuple declaration type info" {
32 }32 }
33}33}
3434
35test "Tuple declaration usage" {35test "tuple declaration usage" {
36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3838
test/behavior/union.zig-70
...@@ -986,76 +986,6 @@ test "function call result coerces from tagged union to the tag" {...@@ -986,76 +986,6 @@ test "function call result coerces from tagged union to the tag" {
986 try comptime S.doTheTest();986 try comptime S.doTheTest();
987}987}
988988
989test "cast from anonymous struct to union" {
990 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
991 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
992 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
993 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
994
995 const S = struct {
996 const U = union(enum) {
997 A: u32,
998 B: []const u8,
999 C: void,
1000 };
1001 fn doTheTest() !void {
1002 var y: u32 = 42;
1003 _ = &y;
1004 const t0 = .{ .A = 123 };
1005 const t1 = .{ .B = "foo" };
1006 const t2 = .{ .C = {} };
1007 const t3 = .{ .A = y };
1008 const x0: U = t0;
1009 var x1: U = t1;
1010 _ = &x1;
1011 const x2: U = t2;
1012 var x3: U = t3;
1013 _ = &x3;
1014 try expect(x0.A == 123);
1015 try expect(std.mem.eql(u8, x1.B, "foo"));
1016 try expect(x2 == .C);
1017 try expect(x3.A == y);
1018 }
1019 };
1020 try S.doTheTest();
1021 try comptime S.doTheTest();
1022}
1023
1024test "cast from pointer to anonymous struct to pointer to union" {
1025 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1026 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1027 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1028 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1029
1030 const S = struct {
1031 const U = union(enum) {
1032 A: u32,
1033 B: []const u8,
1034 C: void,
1035 };
1036 fn doTheTest() !void {
1037 var y: u32 = 42;
1038 _ = &y;
1039 const t0 = &.{ .A = 123 };
1040 const t1 = &.{ .B = "foo" };
1041 const t2 = &.{ .C = {} };
1042 const t3 = &.{ .A = y };
1043 const x0: *const U = t0;
1044 var x1: *const U = t1;
1045 _ = &x1;
1046 const x2: *const U = t2;
1047 var x3: *const U = t3;
1048 _ = &x3;
1049 try expect(x0.A == 123);
1050 try expect(std.mem.eql(u8, x1.B, "foo"));
1051 try expect(x2.* == .C);
1052 try expect(x3.A == y);
1053 }
1054 };
1055 try S.doTheTest();
1056 try comptime S.doTheTest();
1057}
1058
1059test "switching on non exhaustive union" {989test "switching on non exhaustive union" {
1060 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO990 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1061 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO991 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/cases/compile_errors/array slice sentinel mismatch non-scalar.zig +3-2
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1export fn foo() void {1export fn foo() void {
2 const S = struct { a: u32 };2 const S = struct { a: u32 };
3 const sentinel: S = .{ .a = 1 };
3 var arr = [_]S{ .{ .a = 1 }, .{ .a = 2 } };4 var arr = [_]S{ .{ .a = 1 }, .{ .a = 2 } };
4 const s = arr[0..1 :.{ .a = 1 }];5 const s = arr[0..1 :sentinel];
5 _ = s;6 _ = s;
6}7}
78
...@@ -9,5 +10,5 @@ export fn foo() void {...@@ -9,5 +10,5 @@ export fn foo() void {
9// backend=stage210// backend=stage2
10// target=native11// target=native
11//12//
12// :4:26: error: non-scalar sentinel type 'tmp.foo.S'13// :5:25: error: non-scalar sentinel type 'tmp.foo.S'
13// :2:15: note: struct declared here14// :2:15: note: struct declared here
test/cases/compile_errors/bogus_method_call_on_slice.zig+2-1
...@@ -18,4 +18,5 @@ pub export fn entry2() void {...@@ -18,4 +18,5 @@ pub export fn entry2() void {
18//18//
19// :3:6: error: no field or member function named 'copy' in '[]const u8'19// :3:6: error: no field or member function named 'copy' in '[]const u8'
20// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'20// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
21// :12:18: error: no field or member function named 'bar' in 'struct{comptime foo: comptime_int = 1}'21// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_170'
22// :12:6: note: struct declared here
test/cases/compile_errors/coerce_anon_struct.zig created+11
...@@ -0,0 +1,11 @@
1const T = struct { x: u32 };
2export fn foo() void {
3 const a = .{ .x = 123 };
4 _ = @as(T, a);
5}
6
7// error
8//
9// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_159'
10// :3:16: note: struct declared here
11// :1:11: note: struct declared here
test/cases/compile_errors/destructure_error_union.zig+1-1
...@@ -10,6 +10,6 @@ pub export fn entry() void {...@@ -10,6 +10,6 @@ pub export fn entry() void {
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
13// :4:28: error: type 'anyerror!tmp.entry.Foo' cannot be destructured13// :4:28: error: type 'anyerror!struct { u8, u8 }' cannot be destructured
14// :4:26: note: result destructured here14// :4:26: note: result destructured here
15// :4:28: note: consider using 'try', 'catch', or 'if'15// :4:28: note: consider using 'try', 'catch', or 'if'
test/cases/compile_errors/file_level_tuple.zig created+6
...@@ -0,0 +1,6 @@
1u32,
2comptime u8 = 123,
3
4// error
5//
6// :1:1: error: file cannot be a tuple
test/cases/compile_errors/invalid_peer_type_resolution.zig+6-16
...@@ -10,11 +10,6 @@ export fn badTupleField() void {...@@ -10,11 +10,6 @@ export fn badTupleField() void {
10 _ = .{ &x, &y };10 _ = .{ &x, &y };
11 _ = @TypeOf(x, y);11 _ = @TypeOf(x, y);
12}12}
13export fn badNestedField() void {
14 const x = .{ .foo = "hi", .bar = .{ 0, 1 } };
15 const y = .{ .foo = "hello", .bar = .{ 2, "hi" } };
16 _ = @TypeOf(x, y);
17}
18export fn incompatiblePointers() void {13export fn incompatiblePointers() void {
19 const x: []const u8 = "foo";14 const x: []const u8 = "foo";
20 const y: [*:0]const u8 = "bar";15 const y: [*:0]const u8 = "bar";
...@@ -39,14 +34,9 @@ export fn incompatiblePointers4() void {...@@ -39,14 +34,9 @@ export fn incompatiblePointers4() void {
39// :11:9: note: incompatible types: 'u32' and '*const [5:0]u8'34// :11:9: note: incompatible types: 'u32' and '*const [5:0]u8'
40// :11:17: note: type 'u32' here35// :11:17: note: type 'u32' here
41// :11:20: note: type '*const [5:0]u8' here36// :11:20: note: type '*const [5:0]u8' here
42// :16:9: error: struct field 'bar' has conflicting types37// :16:9: error: incompatible types: '[]const u8' and '[*:0]const u8'
43// :16:9: note: struct field '1' has conflicting types38// :16:17: note: type '[]const u8' here
44// :16:9: note: incompatible types: 'comptime_int' and '*const [2:0]u8'39// :16:20: note: type '[*:0]const u8' here
45// :16:17: note: type 'comptime_int' here40// :23:9: error: incompatible types: '[]const u8' and '[*]const u8'
46// :16:20: note: type '*const [2:0]u8' here41// :23:23: note: type '[]const u8' here
47// :21:9: error: incompatible types: '[]const u8' and '[*:0]const u8'42// :23:26: note: type '[*]const u8' here
48// :21:17: note: type '[]const u8' here
49// :21:20: note: type '[*:0]const u8' here
50// :28:9: error: incompatible types: '[]const u8' and '[*]const u8'
51// :28:23: note: type '[]const u8' here
52// :28:26: note: type '[*]const u8' here
test/cases/compile_errors/missing_field_in_struct_value_expression.zig-2
...@@ -29,7 +29,5 @@ export fn h() void {...@@ -29,7 +29,5 @@ export fn h() void {
29// :9:16: error: missing struct field: x29// :9:16: error: missing struct field: x
30// :1:11: note: struct declared here30// :1:11: note: struct declared here
31// :18:16: error: missing tuple field with index 131// :18:16: error: missing tuple field with index 1
32// :16:11: note: struct declared here
33// :22:16: error: missing tuple field with index 032// :22:16: error: missing tuple field with index 0
34// :22:16: note: missing tuple field with index 133// :22:16: note: missing tuple field with index 1
35// :16:11: note: struct declared here
test/cases/compile_errors/overflow_arithmetic_on_vector_with_undefined_elems.zig+3-3
...@@ -21,6 +21,6 @@ comptime {...@@ -21,6 +21,6 @@ comptime {
21// :14:5: note: also here21// :14:5: note: also here
22//22//
23// Compile Log Output:23// Compile Log Output:
24// @as(struct{@Vector(3, u8), @Vector(3, u1)}, .{ .{ 2, 144, undefined }, .{ 0, 1, undefined } })24// @as(struct { @Vector(3, u8), @Vector(3, u1) }, .{ .{ 2, 144, undefined }, .{ 0, 1, undefined } })
25// @as(struct{@Vector(3, u8), @Vector(3, u1)}, .{ .{ 1, 255, undefined }, .{ 0, 1, undefined } })25// @as(struct { @Vector(3, u8), @Vector(3, u1) }, .{ .{ 1, 255, undefined }, .{ 0, 1, undefined } })
26// @as(struct{@Vector(3, u8), @Vector(3, u1)}, .{ .{ 1, 64, undefined }, .{ 0, 1, undefined } })26// @as(struct { @Vector(3, u8), @Vector(3, u1) }, .{ .{ 1, 64, undefined }, .{ 0, 1, undefined } })
test/cases/compile_errors/tuple_init_edge_cases.zig+1-2
...@@ -72,6 +72,5 @@ pub export fn entry6() void {...@@ -72,6 +72,5 @@ pub export fn entry6() void {
72// :18:14: error: missing tuple field with index 172// :18:14: error: missing tuple field with index 1
73// :25:14: error: missing tuple field with index 173// :25:14: error: missing tuple field with index 1
74// :43:14: error: expected at most 2 tuple fields; found 374// :43:14: error: expected at most 2 tuple fields; found 3
75// :50:30: error: index '2' out of bounds of tuple 'struct{comptime comptime_int = 123, u32}'75// :50:30: error: index '2' out of bounds of tuple 'struct { comptime comptime_int = 123, u32 }'
76// :63:37: error: missing tuple field with index 376// :63:37: error: missing tuple field with index 3
77// :58:32: note: struct declared here
test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig+1-1
...@@ -7,4 +7,4 @@ export fn entry() void {...@@ -7,4 +7,4 @@ export fn entry() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :3:11: error: expected type '@TypeOf(.{})', found 'struct{comptime comptime_int = 1, comptime comptime_int = 2, comptime comptime_int = 3}'10// :3:11: error: expected type '@TypeOf(.{})', found 'struct { comptime comptime_int = 1, comptime comptime_int = 2, comptime comptime_int = 3 }'
test/compare_output.zig+2-2
...@@ -440,7 +440,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -440,7 +440,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
440 cases.add("std.log per scope log level override",440 cases.add("std.log per scope log level override",
441 \\const std = @import("std");441 \\const std = @import("std");
442 \\442 \\
443 \\pub const std_options = .{443 \\pub const std_options: std.Options = .{
444 \\ .log_level = .debug,444 \\ .log_level = .debug,
445 \\ 445 \\
446 \\ .log_scope_levels = &.{446 \\ .log_scope_levels = &.{
...@@ -497,7 +497,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -497,7 +497,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
497 cases.add("std.heap.LoggingAllocator logs to std.log",497 cases.add("std.heap.LoggingAllocator logs to std.log",
498 \\const std = @import("std");498 \\const std = @import("std");
499 \\499 \\
500 \\pub const std_options = .{500 \\pub const std_options: std.Options = .{
501 \\ .log_level = .debug,501 \\ .log_level = .debug,
502 \\ .logFn = log,502 \\ .logFn = log,
503 \\};503 \\};
test/src/Debugger.zig+14-14
...@@ -1532,18 +1532,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -1532,18 +1532,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
1532 ,1532 ,
1533 &.{1533 &.{
1534 \\(lldb) frame variable --show-types -- list0 list0.len list0.capacity list0[0] list0[1] list0[2] list0.0 list0.1 list0.21534 \\(lldb) frame variable --show-types -- list0 list0.len list0.capacity list0[0] list0[1] list0[2] list0.0 list0.1 list0.2
1535 \\(std.multi_array_list.MultiArrayList(main.Elem0)) list0 = len=3 capacity=8 {1535 \\(std.multi_array_list.MultiArrayList(struct { u32, u8, u16 })) list0 = len=3 capacity=8 {
1536 \\ (root.main.Elem0) [0] = {1536 \\ (std.struct { u32, u8, u16 }) [0] = {
1537 \\ (u32) .@"0" = 11537 \\ (u32) .@"0" = 1
1538 \\ (u8) .@"1" = 21538 \\ (u8) .@"1" = 2
1539 \\ (u16) .@"2" = 31539 \\ (u16) .@"2" = 3
1540 \\ }1540 \\ }
1541 \\ (root.main.Elem0) [1] = {1541 \\ (std.struct { u32, u8, u16 }) [1] = {
1542 \\ (u32) .@"0" = 41542 \\ (u32) .@"0" = 4
1543 \\ (u8) .@"1" = 51543 \\ (u8) .@"1" = 5
1544 \\ (u16) .@"2" = 61544 \\ (u16) .@"2" = 6
1545 \\ }1545 \\ }
1546 \\ (root.main.Elem0) [2] = {1546 \\ (std.struct { u32, u8, u16 }) [2] = {
1547 \\ (u32) .@"0" = 71547 \\ (u32) .@"0" = 7
1548 \\ (u8) .@"1" = 81548 \\ (u8) .@"1" = 8
1549 \\ (u16) .@"2" = 91549 \\ (u16) .@"2" = 9
...@@ -1551,17 +1551,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -1551,17 +1551,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
1551 \\}1551 \\}
1552 \\(usize) list0.len = 31552 \\(usize) list0.len = 3
1553 \\(usize) list0.capacity = 81553 \\(usize) list0.capacity = 8
1554 \\(root.main.Elem0) list0[0] = {1554 \\(std.struct { u32, u8, u16 }) list0[0] = {
1555 \\ (u32) .@"0" = 11555 \\ (u32) .@"0" = 1
1556 \\ (u8) .@"1" = 21556 \\ (u8) .@"1" = 2
1557 \\ (u16) .@"2" = 31557 \\ (u16) .@"2" = 3
1558 \\}1558 \\}
1559 \\(root.main.Elem0) list0[1] = {1559 \\(std.struct { u32, u8, u16 }) list0[1] = {
1560 \\ (u32) .@"0" = 41560 \\ (u32) .@"0" = 4
1561 \\ (u8) .@"1" = 51561 \\ (u8) .@"1" = 5
1562 \\ (u16) .@"2" = 61562 \\ (u16) .@"2" = 6
1563 \\}1563 \\}
1564 \\(root.main.Elem0) list0[2] = {1564 \\(std.struct { u32, u8, u16 }) list0[2] = {
1565 \\ (u32) .@"0" = 71565 \\ (u32) .@"0" = 7
1566 \\ (u8) .@"1" = 81566 \\ (u8) .@"1" = 8
1567 \\ (u16) .@"2" = 91567 \\ (u16) .@"2" = 9
...@@ -1582,18 +1582,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -1582,18 +1582,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
1582 \\ (u16) [2] = 91582 \\ (u16) [2] = 9
1583 \\}1583 \\}
1584 \\(lldb) frame variable --show-types -- slice0 slice0.len slice0.capacity slice0[0] slice0[1] slice0[2] slice0.0 slice0.1 slice0.21584 \\(lldb) frame variable --show-types -- slice0 slice0.len slice0.capacity slice0[0] slice0[1] slice0[2] slice0.0 slice0.1 slice0.2
1585 \\(std.multi_array_list.MultiArrayList(main.Elem0).Slice) slice0 = len=3 capacity=8 {1585 \\(std.multi_array_list.MultiArrayList(struct { u32, u8, u16 }).Slice) slice0 = len=3 capacity=8 {
1586 \\ (root.main.Elem0) [0] = {1586 \\ (std.struct { u32, u8, u16 }) [0] = {
1587 \\ (u32) .@"0" = 11587 \\ (u32) .@"0" = 1
1588 \\ (u8) .@"1" = 21588 \\ (u8) .@"1" = 2
1589 \\ (u16) .@"2" = 31589 \\ (u16) .@"2" = 3
1590 \\ }1590 \\ }
1591 \\ (root.main.Elem0) [1] = {1591 \\ (std.struct { u32, u8, u16 }) [1] = {
1592 \\ (u32) .@"0" = 41592 \\ (u32) .@"0" = 4
1593 \\ (u8) .@"1" = 51593 \\ (u8) .@"1" = 5
1594 \\ (u16) .@"2" = 61594 \\ (u16) .@"2" = 6
1595 \\ }1595 \\ }
1596 \\ (root.main.Elem0) [2] = {1596 \\ (std.struct { u32, u8, u16 }) [2] = {
1597 \\ (u32) .@"0" = 71597 \\ (u32) .@"0" = 7
1598 \\ (u8) .@"1" = 81598 \\ (u8) .@"1" = 8
1599 \\ (u16) .@"2" = 91599 \\ (u16) .@"2" = 9
...@@ -1601,17 +1601,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -1601,17 +1601,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
1601 \\}1601 \\}
1602 \\(usize) slice0.len = 31602 \\(usize) slice0.len = 3
1603 \\(usize) slice0.capacity = 81603 \\(usize) slice0.capacity = 8
1604 \\(root.main.Elem0) slice0[0] = {1604 \\(std.struct { u32, u8, u16 }) slice0[0] = {
1605 \\ (u32) .@"0" = 11605 \\ (u32) .@"0" = 1
1606 \\ (u8) .@"1" = 21606 \\ (u8) .@"1" = 2
1607 \\ (u16) .@"2" = 31607 \\ (u16) .@"2" = 3
1608 \\}1608 \\}
1609 \\(root.main.Elem0) slice0[1] = {1609 \\(std.struct { u32, u8, u16 }) slice0[1] = {
1610 \\ (u32) .@"0" = 41610 \\ (u32) .@"0" = 4
1611 \\ (u8) .@"1" = 51611 \\ (u8) .@"1" = 5
1612 \\ (u16) .@"2" = 61612 \\ (u16) .@"2" = 6
1613 \\}1613 \\}
1614 \\(root.main.Elem0) slice0[2] = {1614 \\(std.struct { u32, u8, u16 }) slice0[2] = {
1615 \\ (u32) .@"0" = 71615 \\ (u32) .@"0" = 7
1616 \\ (u8) .@"1" = 81616 \\ (u8) .@"1" = 8
1617 \\ (u16) .@"2" = 91617 \\ (u16) .@"2" = 9
test/standalone/sigpipe/breakpipe.zig+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const build_options = @import("build_options");2const build_options = @import("build_options");
33
4pub const std_options = .{4pub const std_options: std.Options = .{
5 .keep_sigpipe = build_options.keep_sigpipe,5 .keep_sigpipe = build_options.keep_sigpipe,
6};6};
77
test/standalone/simple/issue_7030.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
22
3pub const std_options = .{3pub const std_options: std.Options = .{
4 .logFn = log,4 .logFn = log,
5};5};
66