authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-14 19:23:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:52-07:00
logd18881de1be811c1dff52590223b92c916c4b773
treec4c2f82134654737d0921efc360f900e428d5d92
parent88dbd62bcbac24c09791a7838d2f08c2f540967a

stage2: move anon tuples and anon structs to InternPool


11 files changed, 1147 insertions(+), 1264 deletions(-)

src/InternPool.zig+185-18
......@@ -137,9 +137,14 @@ pub const Key = union(enum) {
137137 payload_type: Index,
138138 },
139139 simple_type: SimpleType,
140 /// If `empty_struct_type` is handled separately, then this value may be
141 /// safely assumed to never be `none`.
140 /// This represents a struct that has been explicitly declared in source code,
141 /// or was created with `@Type`. It is unique and based on a declaration.
142 /// It may be a tuple, if declared like this: `struct {A, B, C}`.
142143 struct_type: StructType,
144 /// This is an anonymous struct or tuple type which has no corresponding
145 /// declaration. It is used for types that have no `struct` keyword in the
146 /// source code, and were not created via `@Type`.
147 anon_struct_type: AnonStructType,
143148 union_type: UnionType,
144149 opaque_type: OpaqueType,
145150 enum_type: EnumType,
......@@ -168,7 +173,7 @@ pub const Key = union(enum) {
168173 /// Each element/field stored as an `Index`.
169174 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
170175 /// so the slice length will be one more than the type's array length.
171 aggregate: Aggregate,
176 aggregate: Key.Aggregate,
172177 /// An instance of a union.
173178 un: Union,
174179
......@@ -222,22 +227,25 @@ pub const Key = union(enum) {
222227 namespace: Module.Namespace.Index,
223228 };
224229
225 /// There are three possibilities here:
226 /// * `@TypeOf(.{})` (untyped empty struct literal)
227 /// - namespace == .none, index == .none
228 /// * A struct which has a namepace, but no fields.
229 /// - index == .none
230 /// * A struct which has fields as well as a namepace.
231230 pub const StructType = struct {
232 /// The `none` tag is used to represent two cases:
233 /// * `@TypeOf(.{})`, in which case `namespace` will also be `none`.
234 /// * A struct with no fields, in which case `namespace` will be populated.
231 /// The `none` tag is used to represent a struct with no fields.
235232 index: Module.Struct.OptionalIndex,
236 /// This will be `none` only in the case of `@TypeOf(.{})`
237 /// (`Index.empty_struct_type`).
233 /// May be `none` if the struct has no declarations.
238234 namespace: Module.Namespace.OptionalIndex,
239235 };
240236
237 pub const AnonStructType = struct {
238 types: []const Index,
239 /// This may be empty, indicating this is a tuple.
240 names: []const NullTerminatedString,
241 /// These elements may be `none`, indicating runtime-known.
242 values: []const Index,
243
244 pub fn isTuple(self: AnonStructType) bool {
245 return self.names.len == 0;
246 }
247 };
248
241249 pub const UnionType = struct {
242250 index: Module.Union.Index,
243251 runtime_tag: RuntimeTag,
......@@ -498,6 +506,12 @@ pub const Key = union(enum) {
498506 std.hash.autoHash(hasher, aggregate.ty);
499507 for (aggregate.fields) |field| std.hash.autoHash(hasher, field);
500508 },
509
510 .anon_struct_type => |anon_struct_type| {
511 for (anon_struct_type.types) |elem| std.hash.autoHash(hasher, elem);
512 for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);
513 for (anon_struct_type.names) |elem| std.hash.autoHash(hasher, elem);
514 },
501515 }
502516 }
503517
......@@ -650,6 +664,12 @@ pub const Key = union(enum) {
650664 if (a_info.ty != b_info.ty) return false;
651665 return std.mem.eql(Index, a_info.fields, b_info.fields);
652666 },
667 .anon_struct_type => |a_info| {
668 const b_info = b.anon_struct_type;
669 return std.mem.eql(Index, a_info.types, b_info.types) and
670 std.mem.eql(Index, a_info.values, b_info.values) and
671 std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
672 },
653673 }
654674 }
655675
......@@ -666,6 +686,7 @@ pub const Key = union(enum) {
666686 .union_type,
667687 .opaque_type,
668688 .enum_type,
689 .anon_struct_type,
669690 => .type_type,
670691
671692 inline .ptr,
......@@ -1020,9 +1041,10 @@ pub const static_keys = [_]Key{
10201041 .{ .simple_type = .var_args_param },
10211042
10221043 // empty_struct_type
1023 .{ .struct_type = .{
1024 .namespace = .none,
1025 .index = .none,
1044 .{ .anon_struct_type = .{
1045 .types = &.{},
1046 .names = &.{},
1047 .values = &.{},
10261048 } },
10271049
10281050 .{ .simple_value = .undefined },
......@@ -1144,6 +1166,12 @@ pub const Tag = enum(u8) {
11441166 /// Module.Struct object allocated for it.
11451167 /// data is Module.Namespace.Index.
11461168 type_struct_ns,
1169 /// An AnonStructType which stores types, names, and values for each field.
1170 /// data is extra index of `TypeStructAnon`.
1171 type_struct_anon,
1172 /// An AnonStructType which has only types and values for each field.
1173 /// data is extra index of `TypeStructAnon`.
1174 type_tuple_anon,
11471175 /// A tagged union type.
11481176 /// `data` is `Module.Union.Index`.
11491177 type_union_tagged,
......@@ -1249,6 +1277,26 @@ pub const Tag = enum(u8) {
12491277 only_possible_value,
12501278 /// data is extra index to Key.Union.
12511279 union_value,
1280 /// An instance of a struct, array, or vector.
1281 /// data is extra index to `Aggregate`.
1282 aggregate,
1283};
1284
1285/// Trailing:
1286/// 0. element: Index for each len
1287/// len is determined by the aggregate type.
1288pub const Aggregate = struct {
1289 /// The type of the aggregate.
1290 ty: Index,
1291};
1292
1293/// Trailing:
1294/// 0. type: Index for each fields_len
1295/// 1. value: Index for each fields_len
1296/// 2. name: NullTerminatedString for each fields_len
1297/// The set of field names is omitted when the `Tag` is `type_tuple_anon`.
1298pub const TypeStructAnon = struct {
1299 fields_len: u32,
12521300};
12531301
12541302/// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to
......@@ -1572,6 +1620,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
15721620}
15731621
15741622pub fn indexToKey(ip: InternPool, index: Index) Key {
1623 assert(index != .none);
15751624 const item = ip.items.get(@enumToInt(index));
15761625 const data = item.data;
15771626 return switch (item.tag) {
......@@ -1659,6 +1708,30 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
16591708 .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(),
16601709 } },
16611710
1711 .type_struct_anon => {
1712 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);
1713 const fields_len = type_struct_anon.data.fields_len;
1714 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
1715 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
1716 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
1717 return .{ .anon_struct_type = .{
1718 .types = @ptrCast([]const Index, types),
1719 .values = @ptrCast([]const Index, values),
1720 .names = @ptrCast([]const NullTerminatedString, names),
1721 } };
1722 },
1723 .type_tuple_anon => {
1724 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);
1725 const fields_len = type_struct_anon.data.fields_len;
1726 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
1727 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
1728 return .{ .anon_struct_type = .{
1729 .types = @ptrCast([]const Index, types),
1730 .values = @ptrCast([]const Index, values),
1731 .names = &.{},
1732 } };
1733 },
1734
16621735 .type_union_untagged => .{ .union_type = .{
16631736 .index = @intToEnum(Module.Union.Index, data),
16641737 .runtime_tag = .none,
......@@ -1797,6 +1870,15 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
17971870 else => unreachable,
17981871 };
17991872 },
1873 .aggregate => {
1874 const extra = ip.extraDataTrail(Aggregate, data);
1875 const len = @intCast(u32, ip.aggregateTypeLen(extra.data.ty));
1876 const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]);
1877 return .{ .aggregate = .{
1878 .ty = extra.data.ty,
1879 .fields = fields,
1880 } };
1881 },
18001882 .union_value => .{ .un = ip.extraData(Key.Union, data) },
18011883 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },
18021884 };
......@@ -1982,6 +2064,45 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
19822064 });
19832065 },
19842066
2067 .anon_struct_type => |anon_struct_type| {
2068 assert(anon_struct_type.types.len == anon_struct_type.values.len);
2069 for (anon_struct_type.types) |elem| assert(elem != .none);
2070
2071 const fields_len = @intCast(u32, anon_struct_type.types.len);
2072 if (anon_struct_type.names.len == 0) {
2073 try ip.extra.ensureUnusedCapacity(
2074 gpa,
2075 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 2),
2076 );
2077 ip.items.appendAssumeCapacity(.{
2078 .tag = .type_tuple_anon,
2079 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
2080 .fields_len = fields_len,
2081 }),
2082 });
2083 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.types));
2084 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.values));
2085 return @intToEnum(Index, ip.items.len - 1);
2086 }
2087
2088 assert(anon_struct_type.names.len == anon_struct_type.types.len);
2089
2090 try ip.extra.ensureUnusedCapacity(
2091 gpa,
2092 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 3),
2093 );
2094 ip.items.appendAssumeCapacity(.{
2095 .tag = .type_struct_anon,
2096 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
2097 .fields_len = fields_len,
2098 }),
2099 });
2100 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.types));
2101 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.values));
2102 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.names));
2103 return @intToEnum(Index, ip.items.len - 1);
2104 },
2105
19852106 .union_type => |union_type| {
19862107 ip.items.appendAssumeCapacity(.{
19872108 .tag = switch (union_type.runtime_tag) {
......@@ -2269,6 +2390,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
22692390 },
22702391
22712392 .aggregate => |aggregate| {
2393 assert(aggregate.ty != .none);
2394 for (aggregate.fields) |elem| assert(elem != .none);
2395 if (aggregate.fields.len != ip.aggregateTypeLen(aggregate.ty)) {
2396 std.debug.print("aggregate fields len = {d}, type len = {d}\n", .{
2397 aggregate.fields.len,
2398 ip.aggregateTypeLen(aggregate.ty),
2399 });
2400 }
2401 assert(aggregate.fields.len == ip.aggregateTypeLen(aggregate.ty));
2402
22722403 if (aggregate.fields.len == 0) {
22732404 ip.items.appendAssumeCapacity(.{
22742405 .tag = .only_possible_value,
......@@ -2276,7 +2407,19 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
22762407 });
22772408 return @intToEnum(Index, ip.items.len - 1);
22782409 }
2279 @panic("TODO");
2410
2411 try ip.extra.ensureUnusedCapacity(
2412 gpa,
2413 @typeInfo(Aggregate).Struct.fields.len + aggregate.fields.len,
2414 );
2415
2416 ip.items.appendAssumeCapacity(.{
2417 .tag = .aggregate,
2418 .data = ip.addExtraAssumeCapacity(Aggregate{
2419 .ty = aggregate.ty,
2420 }),
2421 });
2422 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.fields));
22802423 },
22812424
22822425 .un => |un| {
......@@ -2913,6 +3056,14 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
29133056 .type_opaque => @sizeOf(Key.OpaqueType),
29143057 .type_struct => @sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
29153058 .type_struct_ns => @sizeOf(Module.Namespace),
3059 .type_struct_anon => b: {
3060 const info = ip.extraData(TypeStructAnon, data);
3061 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
3062 },
3063 .type_tuple_anon => b: {
3064 const info = ip.extraData(TypeStructAnon, data);
3065 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 2 * info.fields_len);
3066 },
29163067
29173068 .type_union_tagged,
29183069 .type_union_untagged,
......@@ -2942,6 +3093,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
29423093 },
29433094 .enum_tag => @sizeOf(Key.EnumTag),
29443095
3096 .aggregate => b: {
3097 const info = ip.extraData(Aggregate, data);
3098 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));
3099 break :b @sizeOf(Aggregate) + (@sizeOf(u32) * fields_len);
3100 },
3101
29453102 .float_f16 => 0,
29463103 .float_f32 => 0,
29473104 .float_f64 => @sizeOf(Float64),
......@@ -3079,3 +3236,13 @@ pub fn toEnum(ip: InternPool, comptime E: type, i: Index) E {
30793236 const int = ip.indexToKey(i).enum_tag.int;
30803237 return @intToEnum(E, ip.indexToKey(int).int.storage.u64);
30813238}
3239
3240pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
3241 return switch (ip.indexToKey(ty)) {
3242 .struct_type => |struct_type| ip.structPtrConst(struct_type.index.unwrap() orelse return 0).fields.count(),
3243 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
3244 .array_type => |array_type| array_type.len,
3245 .vector_type => |vector_type| vector_type.len,
3246 else => unreachable,
3247 };
3248}
src/Sema.zig+384-331
......@@ -7896,12 +7896,15 @@ fn resolveGenericInstantiationType(
78967896}
78977897
78987898fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
7899 if (!ty.isSimpleTupleOrAnonStruct()) return;
7900 const tuple = ty.tupleFields();
7901 for (tuple.values, 0..) |field_val, i| {
7902 try sema.resolveTupleLazyValues(block, src, tuple.types[i]);
7903 if (field_val.ip_index == .unreachable_value) continue;
7904 try sema.resolveLazyValue(field_val);
7899 const mod = sema.mod;
7900 const tuple = switch (mod.intern_pool.indexToKey(ty.ip_index)) {
7901 .anon_struct_type => |tuple| tuple,
7902 else => return,
7903 };
7904 for (tuple.types, tuple.values) |field_ty, field_val| {
7905 try sema.resolveTupleLazyValues(block, src, field_ty.toType());
7906 if (field_val == .none) continue;
7907 try sema.resolveLazyValue(field_val.toValue());
79057908 }
79067909}
79077910
......@@ -12038,31 +12041,49 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1203812041 const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs);
1203912042 const field_name = try sema.resolveConstString(block, name_src, extra.rhs, "field name must be comptime-known");
1204012043 const ty = try sema.resolveTypeFields(unresolved_ty);
12044 const ip = &mod.intern_pool;
1204112045
1204212046 const has_field = hf: {
12043 if (ty.isSlice(mod)) {
12044 if (mem.eql(u8, field_name, "ptr")) break :hf true;
12045 if (mem.eql(u8, field_name, "len")) break :hf true;
12046 break :hf false;
12047 }
12048 if (ty.castTag(.anon_struct)) |pl| {
12049 break :hf for (pl.data.names) |name| {
12050 if (mem.eql(u8, name, field_name)) break true;
12051 } else false;
12052 }
12053 if (ty.isTuple(mod)) {
12054 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;
12055 break :hf field_index < ty.structFieldCount(mod);
12056 }
12057 break :hf switch (ty.zigTypeTag(mod)) {
12058 .Struct => ty.structFields(mod).contains(field_name),
12059 .Union => ty.unionFields(mod).contains(field_name),
12060 .Enum => ty.enumFieldIndex(field_name, mod) != null,
12061 .Array => mem.eql(u8, field_name, "len"),
12062 else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{
12063 ty.fmt(sema.mod),
12064 }),
12065 };
12047 switch (ip.indexToKey(ty.ip_index)) {
12048 .ptr_type => |ptr_type| switch (ptr_type.size) {
12049 .Slice => {
12050 if (mem.eql(u8, field_name, "ptr")) break :hf true;
12051 if (mem.eql(u8, field_name, "len")) break :hf true;
12052 break :hf false;
12053 },
12054 else => {},
12055 },
12056 .anon_struct_type => |anon_struct| {
12057 if (anon_struct.names.len != 0) {
12058 // If the string is not interned, then the field certainly is not present.
12059 const name_interned = ip.getString(field_name).unwrap() orelse break :hf false;
12060 break :hf mem.indexOfScalar(InternPool.NullTerminatedString, anon_struct.names, name_interned) != null;
12061 } else {
12062 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;
12063 break :hf field_index < ty.structFieldCount(mod);
12064 }
12065 },
12066 .struct_type => |struct_type| {
12067 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :hf false;
12068 assert(struct_obj.haveFieldTypes());
12069 break :hf struct_obj.fields.contains(field_name);
12070 },
12071 .union_type => |union_type| {
12072 const union_obj = mod.unionPtr(union_type.index);
12073 assert(union_obj.haveFieldTypes());
12074 break :hf union_obj.fields.contains(field_name);
12075 },
12076 .enum_type => |enum_type| {
12077 // If the string is not interned, then the field certainly is not present.
12078 const name_interned = ip.getString(field_name).unwrap() orelse break :hf false;
12079 break :hf enum_type.nameIndex(ip, name_interned) != null;
12080 },
12081 .array_type => break :hf mem.eql(u8, field_name, "len"),
12082 else => {},
12083 }
12084 return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{
12085 ty.fmt(sema.mod),
12086 });
1206612087 };
1206712088 if (has_field) {
1206812089 return Air.Inst.Ref.bool_true;
......@@ -12632,42 +12653,48 @@ fn analyzeTupleCat(
1263212653 }
1263312654 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);
1263412655
12635 const types = try sema.arena.alloc(Type, final_len);
12636 const values = try sema.arena.alloc(Value, final_len);
12656 const types = try sema.arena.alloc(InternPool.Index, final_len);
12657 const values = try sema.arena.alloc(InternPool.Index, final_len);
1263712658
1263812659 const opt_runtime_src = rs: {
1263912660 var runtime_src: ?LazySrcLoc = null;
1264012661 var i: u32 = 0;
1264112662 while (i < lhs_len) : (i += 1) {
12642 types[i] = lhs_ty.structFieldType(i, mod);
12663 types[i] = lhs_ty.structFieldType(i, mod).ip_index;
1264312664 const default_val = lhs_ty.structFieldDefaultValue(i, mod);
12644 values[i] = default_val;
12665 values[i] = default_val.ip_index;
1264512666 const operand_src = lhs_src; // TODO better source location
1264612667 if (default_val.ip_index == .unreachable_value) {
1264712668 runtime_src = operand_src;
12669 values[i] = .none;
1264812670 }
1264912671 }
1265012672 i = 0;
1265112673 while (i < rhs_len) : (i += 1) {
12652 types[i + lhs_len] = rhs_ty.structFieldType(i, mod);
12674 types[i + lhs_len] = rhs_ty.structFieldType(i, mod).ip_index;
1265312675 const default_val = rhs_ty.structFieldDefaultValue(i, mod);
12654 values[i + lhs_len] = default_val;
12676 values[i + lhs_len] = default_val.ip_index;
1265512677 const operand_src = rhs_src; // TODO better source location
1265612678 if (default_val.ip_index == .unreachable_value) {
1265712679 runtime_src = operand_src;
12680 values[i + lhs_len] = .none;
1265812681 }
1265912682 }
1266012683 break :rs runtime_src;
1266112684 };
1266212685
12663 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
12686 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
1266412687 .types = types,
1266512688 .values = values,
12666 });
12689 .names = &.{},
12690 } });
1266712691
1266812692 const runtime_src = opt_runtime_src orelse {
12669 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
12670 return sema.addConstant(tuple_ty, tuple_val);
12693 const tuple_val = try mod.intern(.{ .aggregate = .{
12694 .ty = tuple_ty,
12695 .fields = values,
12696 } });
12697 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
1267112698 };
1267212699
1267312700 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -12685,7 +12712,7 @@ fn analyzeTupleCat(
1268512712 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);
1268612713 }
1268712714
12688 return block.addAggregateInit(tuple_ty, element_refs);
12715 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1268912716}
1269012717
1269112718fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -12938,7 +12965,7 @@ fn analyzeTupleMul(
1293812965 block: *Block,
1293912966 src_node: i32,
1294012967 operand: Air.Inst.Ref,
12941 factor: u64,
12968 factor: usize,
1294212969) CompileError!Air.Inst.Ref {
1294312970 const mod = sema.mod;
1294412971 const operand_ty = sema.typeOf(operand);
......@@ -12947,44 +12974,45 @@ fn analyzeTupleMul(
1294712974 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1294812975
1294912976 const tuple_len = operand_ty.structFieldCount(mod);
12950 const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch
12977 const final_len = std.math.mul(usize, tuple_len, factor) catch
1295112978 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1295212979
12953 if (final_len_u64 == 0) {
12980 if (final_len == 0) {
1295412981 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);
1295512982 }
12956 const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);
12957
12958 const types = try sema.arena.alloc(Type, final_len);
12959 const values = try sema.arena.alloc(Value, final_len);
12983 const types = try sema.arena.alloc(InternPool.Index, final_len);
12984 const values = try sema.arena.alloc(InternPool.Index, final_len);
1296012985
1296112986 const opt_runtime_src = rs: {
1296212987 var runtime_src: ?LazySrcLoc = null;
12963 var i: u32 = 0;
12964 while (i < tuple_len) : (i += 1) {
12965 types[i] = operand_ty.structFieldType(i, mod);
12966 values[i] = operand_ty.structFieldDefaultValue(i, mod);
12988 for (0..tuple_len) |i| {
12989 types[i] = operand_ty.structFieldType(i, mod).ip_index;
12990 values[i] = operand_ty.structFieldDefaultValue(i, mod).ip_index;
1296712991 const operand_src = lhs_src; // TODO better source location
12968 if (values[i].ip_index == .unreachable_value) {
12992 if (values[i] == .unreachable_value) {
1296912993 runtime_src = operand_src;
12994 values[i] = .none; // TODO don't treat unreachable_value as special
1297012995 }
1297112996 }
12972 i = 0;
12973 while (i < factor) : (i += 1) {
12974 mem.copyForwards(Type, types[tuple_len * i ..], types[0..tuple_len]);
12975 mem.copyForwards(Value, values[tuple_len * i ..], values[0..tuple_len]);
12997 for (0..factor) |i| {
12998 mem.copyForwards(InternPool.Index, types[tuple_len * i ..], types[0..tuple_len]);
12999 mem.copyForwards(InternPool.Index, values[tuple_len * i ..], values[0..tuple_len]);
1297613000 }
1297713001 break :rs runtime_src;
1297813002 };
1297913003
12980 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
13004 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
1298113005 .types = types,
1298213006 .values = values,
12983 });
13007 .names = &.{},
13008 } });
1298413009
1298513010 const runtime_src = opt_runtime_src orelse {
12986 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
12987 return sema.addConstant(tuple_ty, tuple_val);
13011 const tuple_val = try mod.intern(.{ .aggregate = .{
13012 .ty = tuple_ty,
13013 .fields = values,
13014 } });
13015 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
1298813016 };
1298913017
1299013018 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -13000,7 +13028,7 @@ fn analyzeTupleMul(
1300013028 @memcpy(element_refs[tuple_len * i ..][0..tuple_len], element_refs[0..tuple_len]);
1300113029 }
1300213030
13003 return block.addAggregateInit(tuple_ty, element_refs);
13031 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1300413032}
1300513033
1300613034fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -13020,7 +13048,8 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1302013048 if (lhs_ty.isTuple(mod)) {
1302113049 // In `**` rhs must be comptime-known, but lhs can be runtime-known
1302213050 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
13023 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);
13051 const factor_casted = try sema.usizeCast(block, rhs_src, factor);
13052 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor_casted);
1302413053 }
1302513054
1302613055 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
......@@ -14533,19 +14562,14 @@ fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
1453314562 .child = .u1_type,
1453414563 }) else Type.u1;
1453514564
14536 const types = try sema.arena.alloc(Type, 2);
14537 const values = try sema.arena.alloc(Value, 2);
14538 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
14539 .types = types,
14540 .values = values,
14541 });
14542
14543 types[0] = ty;
14544 types[1] = ov_ty;
14545 values[0] = Value.@"unreachable";
14546 values[1] = Value.@"unreachable";
14547
14548 return tuple_ty;
14565 const types = [2]InternPool.Index{ ty.ip_index, ov_ty.ip_index };
14566 const values = [2]InternPool.Index{ .none, .none };
14567 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
14568 .types = &types,
14569 .values = &values,
14570 .names = &.{},
14571 } });
14572 return tuple_ty.toType();
1454914573}
1455014574
1455114575fn analyzeArithmetic(
......@@ -16506,57 +16530,66 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1650616530 const layout = struct_ty.containerLayout(mod);
1650716531
1650816532 const struct_field_vals = fv: {
16509 if (struct_ty.isSimpleTupleOrAnonStruct()) {
16510 const tuple = struct_ty.tupleFields();
16511 const field_types = tuple.types;
16512 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);
16513 for (struct_field_vals, 0..) |*struct_field_val, i| {
16514 const field_ty = field_types[i];
16515 const name_val = v: {
16516 var anon_decl = try block.startAnonDecl();
16517 defer anon_decl.deinit();
16518 const bytes = if (struct_ty.castTag(.anon_struct)) |payload|
16519 try anon_decl.arena().dupeZ(u8, payload.data.names[i])
16520 else
16521 try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
16522 const new_decl = try anon_decl.finish(
16523 try Type.array(anon_decl.arena(), bytes.len, Value.zero_u8, Type.u8, mod),
16524 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16525 0, // default alignment
16526 );
16527 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
16528 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
16529 .len = try mod.intValue(Type.usize, bytes.len),
16530 });
16531 };
16532
16533 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
16534 const field_val = tuple.values[i];
16535 const is_comptime = field_val.ip_index != .unreachable_value;
16536 const opt_default_val = if (is_comptime) field_val else null;
16537 const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val);
16538 struct_field_fields.* = .{
16539 // name: []const u8,
16540 name_val,
16541 // type: type,
16542 try Value.Tag.ty.create(fields_anon_decl.arena(), field_ty),
16543 // default_value: ?*const anyopaque,
16544 try default_val_ptr.copy(fields_anon_decl.arena()),
16545 // is_comptime: bool,
16546 Value.makeBool(is_comptime),
16547 // alignment: comptime_int,
16548 try field_ty.lazyAbiAlignment(mod, fields_anon_decl.arena()),
16549 };
16550 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16551 }
16552 break :fv struct_field_vals;
16553 }
16554 const struct_fields = struct_ty.structFields(mod);
16555 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());
16533 const struct_type = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
16534 .anon_struct_type => |tuple| {
16535 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, tuple.types.len);
16536 for (
16537 tuple.types,
16538 tuple.values,
16539 struct_field_vals,
16540 0..,
16541 ) |field_ty, field_val, *struct_field_val, i| {
16542 const name_val = v: {
16543 var anon_decl = try block.startAnonDecl();
16544 defer anon_decl.deinit();
16545 const bytes = if (tuple.names.len != 0)
16546 // https://github.com/ziglang/zig/issues/15709
16547 @as([]const u8, mod.intern_pool.stringToSlice(tuple.names[i]))
16548 else
16549 try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
16550 const new_decl = try anon_decl.finish(
16551 try Type.array(anon_decl.arena(), bytes.len, Value.zero_u8, Type.u8, mod),
16552 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16553 0, // default alignment
16554 );
16555 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
16556 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
16557 .len = try mod.intValue(Type.usize, bytes.len),
16558 });
16559 };
1655616560
16557 for (struct_field_vals, 0..) |*field_val, i| {
16558 const field = struct_fields.values()[i];
16559 const name = struct_fields.keys()[i];
16561 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
16562 const is_comptime = field_val != .none;
16563 const opt_default_val = if (is_comptime) field_val.toValue() else null;
16564 const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);
16565 struct_field_fields.* = .{
16566 // name: []const u8,
16567 name_val,
16568 // type: type,
16569 field_ty.toValue(),
16570 // default_value: ?*const anyopaque,
16571 try default_val_ptr.copy(fields_anon_decl.arena()),
16572 // is_comptime: bool,
16573 Value.makeBool(is_comptime),
16574 // alignment: comptime_int,
16575 try field_ty.toType().lazyAbiAlignment(mod, fields_anon_decl.arena()),
16576 };
16577 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16578 }
16579 break :fv struct_field_vals;
16580 },
16581 .struct_type => |s| s,
16582 else => unreachable,
16583 };
16584 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
16585 break :fv &[0]Value{};
16586 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_obj.fields.count());
16587
16588 for (
16589 struct_field_vals,
16590 struct_obj.fields.keys(),
16591 struct_obj.fields.values(),
16592 ) |*field_val, name, field| {
1656016593 const name_val = v: {
1656116594 var anon_decl = try block.startAnonDecl();
1656216595 defer anon_decl.deinit();
......@@ -18013,7 +18046,7 @@ fn zirStructInit(
1801318046 try sema.requireRuntimeBlock(block, src, null);
1801418047 try sema.queueFullTypeResolution(resolved_ty);
1801518048 return block.addUnionInit(resolved_ty, field_index, init_inst);
18016 } else if (resolved_ty.isAnonStruct()) {
18049 } else if (resolved_ty.isAnonStruct(mod)) {
1801718050 return sema.fail(block, src, "TODO anon struct init validation", .{});
1801818051 }
1801918052 unreachable;
......@@ -18034,60 +18067,54 @@ fn finishStructInit(
1803418067 var root_msg: ?*Module.ErrorMsg = null;
1803518068 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
1803618069
18037 if (struct_ty.isAnonStruct()) {
18038 const struct_obj = struct_ty.castTag(.anon_struct).?.data;
18039 for (struct_obj.values, 0..) |default_val, i| {
18040 if (field_inits[i] != .none) continue;
18041
18042 if (default_val.ip_index == .unreachable_value) {
18043 const field_name = struct_obj.names[i];
18044 const template = "missing struct field: {s}";
18045 const args = .{field_name};
18046 if (root_msg) |msg| {
18047 try sema.errNote(block, init_src, msg, template, args);
18048 } else {
18049 root_msg = try sema.errMsg(block, init_src, template, args);
18050 }
18051 } else {
18052 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
18053 }
18054 }
18055 } else if (struct_ty.isTuple(mod)) {
18056 var i: u32 = 0;
18057 const len = struct_ty.structFieldCount(mod);
18058 while (i < len) : (i += 1) {
18059 if (field_inits[i] != .none) continue;
18070 switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
18071 .anon_struct_type => |anon_struct| {
18072 for (anon_struct.types, anon_struct.values, 0..) |field_ty, default_val, i| {
18073 if (field_inits[i] != .none) continue;
1806018074
18061 const default_val = struct_ty.structFieldDefaultValue(i, mod);
18062 if (default_val.ip_index == .unreachable_value) {
18063 const template = "missing tuple field with index {d}";
18064 if (root_msg) |msg| {
18065 try sema.errNote(block, init_src, msg, template, .{i});
18075 if (default_val == .none) {
18076 if (anon_struct.names.len == 0) {
18077 const template = "missing tuple field with index {d}";
18078 if (root_msg) |msg| {
18079 try sema.errNote(block, init_src, msg, template, .{i});
18080 } else {
18081 root_msg = try sema.errMsg(block, init_src, template, .{i});
18082 }
18083 } else {
18084 const field_name = mod.intern_pool.stringToSlice(anon_struct.names[i]);
18085 const template = "missing struct field: {s}";
18086 const args = .{field_name};
18087 if (root_msg) |msg| {
18088 try sema.errNote(block, init_src, msg, template, args);
18089 } else {
18090 root_msg = try sema.errMsg(block, init_src, template, args);
18091 }
18092 }
1806618093 } else {
18067 root_msg = try sema.errMsg(block, init_src, template, .{i});
18094 field_inits[i] = try sema.addConstant(field_ty.toType(), default_val.toValue());
1806818095 }
18069 } else {
18070 field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i, mod), default_val);
1807118096 }
18072 }
18073 } else {
18074 const struct_obj = mod.typeToStruct(struct_ty).?;
18075 for (struct_obj.fields.values(), 0..) |field, i| {
18076 if (field_inits[i] != .none) continue;
18097 },
18098 .struct_type => |struct_type| {
18099 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
18100 for (struct_obj.fields.values(), 0..) |field, i| {
18101 if (field_inits[i] != .none) continue;
1807718102
18078 if (field.default_val.ip_index == .unreachable_value) {
18079 const field_name = struct_obj.fields.keys()[i];
18080 const template = "missing struct field: {s}";
18081 const args = .{field_name};
18082 if (root_msg) |msg| {
18083 try sema.errNote(block, init_src, msg, template, args);
18103 if (field.default_val.ip_index == .unreachable_value) {
18104 const field_name = struct_obj.fields.keys()[i];
18105 const template = "missing struct field: {s}";
18106 const args = .{field_name};
18107 if (root_msg) |msg| {
18108 try sema.errNote(block, init_src, msg, template, args);
18109 } else {
18110 root_msg = try sema.errMsg(block, init_src, template, args);
18111 }
1808418112 } else {
18085 root_msg = try sema.errMsg(block, init_src, template, args);
18113 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
1808618114 }
18087 } else {
18088 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
1808918115 }
18090 }
18116 },
18117 else => unreachable,
1809118118 }
1809218119
1809318120 if (root_msg) |msg| {
......@@ -18159,31 +18186,33 @@ fn zirStructInitAnon(
1815918186 is_ref: bool,
1816018187) CompileError!Air.Inst.Ref {
1816118188 const mod = sema.mod;
18189 const gpa = sema.gpa;
1816218190 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1816318191 const src = inst_data.src();
1816418192 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
18165 const types = try sema.arena.alloc(Type, extra.data.fields_len);
18166 const values = try sema.arena.alloc(Value, types.len);
18167 var fields = std.StringArrayHashMapUnmanaged(u32){};
18168 defer fields.deinit(sema.gpa);
18169 try fields.ensureUnusedCapacity(sema.gpa, types.len);
18193 const types = try sema.arena.alloc(InternPool.Index, extra.data.fields_len);
18194 const values = try sema.arena.alloc(InternPool.Index, types.len);
18195 var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena);
18196 try fields.ensureUnusedCapacity(types.len);
1817018197
1817118198 // Find which field forces the expression to be runtime, if any.
1817218199 const opt_runtime_index = rs: {
1817318200 var runtime_index: ?usize = null;
1817418201 var extra_index = extra.end;
18175 for (types, 0..) |*field_ty, i| {
18202 for (types, 0..) |*field_ty, i_usize| {
18203 const i = @intCast(u32, i_usize);
1817618204 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
1817718205 extra_index = item.end;
1817818206
1817918207 const name = sema.code.nullTerminatedString(item.data.field_name);
18180 const gop = fields.getOrPutAssumeCapacity(name);
18208 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
18209 const gop = fields.getOrPutAssumeCapacity(name_ip);
1818118210 if (gop.found_existing) {
1818218211 const msg = msg: {
1818318212 const decl = sema.mod.declPtr(block.src_decl);
1818418213 const field_src = mod.initSrc(src.node_offset.x, decl, i);
1818518214 const msg = try sema.errMsg(block, field_src, "duplicate field", .{});
18186 errdefer msg.destroy(sema.gpa);
18215 errdefer msg.destroy(gpa);
1818718216
1818818217 const prev_source = mod.initSrc(src.node_offset.x, decl, gop.value_ptr.*);
1818918218 try sema.errNote(block, prev_source, msg, "other field here", .{});
......@@ -18191,41 +18220,44 @@ fn zirStructInitAnon(
1819118220 };
1819218221 return sema.failWithOwnedErrorMsg(msg);
1819318222 }
18194 gop.value_ptr.* = @intCast(u32, i);
18223 gop.value_ptr.* = i;
1819518224
1819618225 const init = try sema.resolveInst(item.data.init);
18197 field_ty.* = sema.typeOf(init);
18198 if (types[i].zigTypeTag(mod) == .Opaque) {
18226 field_ty.* = sema.typeOf(init).ip_index;
18227 if (types[i].toType().zigTypeTag(mod) == .Opaque) {
1819918228 const msg = msg: {
1820018229 const decl = sema.mod.declPtr(block.src_decl);
1820118230 const field_src = mod.initSrc(src.node_offset.x, decl, i);
1820218231 const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
1820318232 errdefer msg.destroy(sema.gpa);
1820418233
18205 try sema.addDeclaredHereNote(msg, types[i]);
18234 try sema.addDeclaredHereNote(msg, types[i].toType());
1820618235 break :msg msg;
1820718236 };
1820818237 return sema.failWithOwnedErrorMsg(msg);
1820918238 }
1821018239 if (try sema.resolveMaybeUndefVal(init)) |init_val| {
18211 values[i] = init_val;
18240 values[i] = init_val.ip_index;
1821218241 } else {
18213 values[i] = Value.@"unreachable";
18242 values[i] = .none;
1821418243 runtime_index = i;
1821518244 }
1821618245 }
1821718246 break :rs runtime_index;
1821818247 };
1821918248
18220 const tuple_ty = try Type.Tag.anon_struct.create(sema.arena, .{
18221 .names = try sema.arena.dupe([]const u8, fields.keys()),
18249 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
18250 .names = fields.keys(),
1822218251 .types = types,
1822318252 .values = values,
18224 });
18253 } });
1822518254
1822618255 const runtime_index = opt_runtime_index orelse {
18227 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
18228 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);
18256 const tuple_val = try mod.intern(.{ .aggregate = .{
18257 .ty = tuple_ty,
18258 .fields = values,
18259 } });
18260 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
1822918261 };
1823018262
1823118263 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
......@@ -18241,7 +18273,7 @@ fn zirStructInitAnon(
1824118273 if (is_ref) {
1824218274 const target = sema.mod.getTarget();
1824318275 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18244 .pointee_type = tuple_ty,
18276 .pointee_type = tuple_ty.toType(),
1824518277 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1824618278 });
1824718279 const alloc = try block.addTy(.alloc, alloc_ty);
......@@ -18254,9 +18286,9 @@ fn zirStructInitAnon(
1825418286 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
1825518287 .mutable = true,
1825618288 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18257 .pointee_type = field_ty,
18289 .pointee_type = field_ty.toType(),
1825818290 });
18259 if (values[i].ip_index == .unreachable_value) {
18291 if (values[i] == .none) {
1826018292 const init = try sema.resolveInst(item.data.init);
1826118293 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
1826218294 _ = try block.addBinOp(.store, field_ptr, init);
......@@ -18274,7 +18306,7 @@ fn zirStructInitAnon(
1827418306 element_refs[i] = try sema.resolveInst(item.data.init);
1827518307 }
1827618308
18277 return block.addAggregateInit(tuple_ty, element_refs);
18309 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1827818310}
1827918311
1828018312fn zirArrayInit(
......@@ -18400,43 +18432,47 @@ fn zirArrayInitAnon(
1840018432 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);
1840118433 const mod = sema.mod;
1840218434
18403 const types = try sema.arena.alloc(Type, operands.len);
18404 const values = try sema.arena.alloc(Value, operands.len);
18435 const types = try sema.arena.alloc(InternPool.Index, operands.len);
18436 const values = try sema.arena.alloc(InternPool.Index, operands.len);
1840518437
1840618438 const opt_runtime_src = rs: {
1840718439 var runtime_src: ?LazySrcLoc = null;
1840818440 for (operands, 0..) |operand, i| {
1840918441 const operand_src = src; // TODO better source location
1841018442 const elem = try sema.resolveInst(operand);
18411 types[i] = sema.typeOf(elem);
18412 if (types[i].zigTypeTag(mod) == .Opaque) {
18443 types[i] = sema.typeOf(elem).ip_index;
18444 if (types[i].toType().zigTypeTag(mod) == .Opaque) {
1841318445 const msg = msg: {
1841418446 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
1841518447 errdefer msg.destroy(sema.gpa);
1841618448
18417 try sema.addDeclaredHereNote(msg, types[i]);
18449 try sema.addDeclaredHereNote(msg, types[i].toType());
1841818450 break :msg msg;
1841918451 };
1842018452 return sema.failWithOwnedErrorMsg(msg);
1842118453 }
1842218454 if (try sema.resolveMaybeUndefVal(elem)) |val| {
18423 values[i] = val;
18455 values[i] = val.ip_index;
1842418456 } else {
18425 values[i] = Value.@"unreachable";
18457 values[i] = .none;
1842618458 runtime_src = operand_src;
1842718459 }
1842818460 }
1842918461 break :rs runtime_src;
1843018462 };
1843118463
18432 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
18464 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
1843318465 .types = types,
1843418466 .values = values,
18435 });
18467 .names = &.{},
18468 } });
1843618469
1843718470 const runtime_src = opt_runtime_src orelse {
18438 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
18439 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);
18471 const tuple_val = try mod.intern(.{ .aggregate = .{
18472 .ty = tuple_ty,
18473 .fields = values,
18474 } });
18475 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
1844018476 };
1844118477
1844218478 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -18444,7 +18480,7 @@ fn zirArrayInitAnon(
1844418480 if (is_ref) {
1844518481 const target = sema.mod.getTarget();
1844618482 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18447 .pointee_type = tuple_ty,
18483 .pointee_type = tuple_ty.toType(),
1844818484 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1844918485 });
1845018486 const alloc = try block.addTy(.alloc, alloc_ty);
......@@ -18453,9 +18489,9 @@ fn zirArrayInitAnon(
1845318489 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
1845418490 .mutable = true,
1845518491 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18456 .pointee_type = types[i],
18492 .pointee_type = types[i].toType(),
1845718493 });
18458 if (values[i].ip_index == .unreachable_value) {
18494 if (values[i] == .none) {
1845918495 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
1846018496 _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand));
1846118497 }
......@@ -18469,7 +18505,7 @@ fn zirArrayInitAnon(
1846918505 element_refs[i] = try sema.resolveInst(operand);
1847018506 }
1847118507
18472 return block.addAggregateInit(tuple_ty, element_refs);
18508 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1847318509}
1847418510
1847518511fn addConstantMaybeRef(
......@@ -18532,15 +18568,18 @@ fn fieldType(
1853218568 const resolved_ty = try sema.resolveTypeFields(cur_ty);
1853318569 cur_ty = resolved_ty;
1853418570 switch (cur_ty.zigTypeTag(mod)) {
18535 .Struct => {
18536 if (cur_ty.isAnonStruct()) {
18571 .Struct => switch (mod.intern_pool.indexToKey(cur_ty.ip_index)) {
18572 .anon_struct_type => |anon_struct| {
1853718573 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
18538 return sema.addType(cur_ty.tupleFields().types[field_index]);
18539 }
18540 const struct_obj = mod.typeToStruct(cur_ty).?;
18541 const field = struct_obj.fields.get(field_name) orelse
18542 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
18543 return sema.addType(field.ty);
18574 return sema.addType(anon_struct.types[field_index].toType());
18575 },
18576 .struct_type => |struct_type| {
18577 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
18578 const field = struct_obj.fields.get(field_name) orelse
18579 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
18580 return sema.addType(field.ty);
18581 },
18582 else => unreachable,
1854418583 },
1854518584 .Union => {
1854618585 const union_obj = mod.typeToUnion(cur_ty).?;
......@@ -24697,7 +24736,7 @@ fn structFieldPtr(
2469724736 }
2469824737 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
2469924738 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
24700 } else if (struct_ty.isAnonStruct()) {
24739 } else if (struct_ty.isAnonStruct(mod)) {
2470124740 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
2470224741 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
2470324742 }
......@@ -24721,11 +24760,11 @@ fn structFieldPtrByIndex(
2472124760 struct_ty: Type,
2472224761 initializing: bool,
2472324762) CompileError!Air.Inst.Ref {
24724 if (struct_ty.isAnonStruct()) {
24763 const mod = sema.mod;
24764 if (struct_ty.isAnonStruct(mod)) {
2472524765 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);
2472624766 }
2472724767
24728 const mod = sema.mod;
2472924768 const struct_obj = mod.typeToStruct(struct_ty).?;
2473024769 const field = struct_obj.fields.values()[field_index];
2473124770 const struct_ptr_ty = sema.typeOf(struct_ptr);
......@@ -24830,45 +24869,42 @@ fn structFieldVal(
2483024869 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
2483124870
2483224871 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24833 switch (struct_ty.ip_index) {
24834 .empty_struct_type => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24835 .none => switch (struct_ty.tag()) {
24836 .tuple => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24837 .anon_struct => {
24838 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24839 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24840 },
24841 else => unreachable,
24842 },
24843 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
24844 .struct_type => |struct_type| {
24845 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
24846 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
24872 switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
24873 .struct_type => |struct_type| {
24874 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
24875 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2484724876
24848 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24849 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
24850 const field_index = @intCast(u32, field_index_usize);
24851 const field = struct_obj.fields.values()[field_index];
24852
24853 if (field.is_comptime) {
24854 return sema.addConstant(field.ty, field.default_val);
24855 }
24877 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24878 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
24879 const field_index = @intCast(u32, field_index_usize);
24880 const field = struct_obj.fields.values()[field_index];
2485624881
24857 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {
24858 if (struct_val.isUndef(mod)) return sema.addConstUndef(field.ty);
24859 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24860 return sema.addConstant(field.ty, opv);
24861 }
24882 if (field.is_comptime) {
24883 return sema.addConstant(field.ty, field.default_val);
24884 }
2486224885
24863 const field_values = struct_val.castTag(.aggregate).?.data;
24864 return sema.addConstant(field.ty, field_values[field_index]);
24886 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {
24887 if (struct_val.isUndef(mod)) return sema.addConstUndef(field.ty);
24888 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24889 return sema.addConstant(field.ty, opv);
2486524890 }
2486624891
24867 try sema.requireRuntimeBlock(block, src, null);
24868 return block.addStructFieldVal(struct_byval, field_index, field.ty);
24869 },
24870 else => unreachable,
24892 const field_values = struct_val.castTag(.aggregate).?.data;
24893 return sema.addConstant(field.ty, field_values[field_index]);
24894 }
24895
24896 try sema.requireRuntimeBlock(block, src, null);
24897 return block.addStructFieldVal(struct_byval, field_index, field.ty);
24898 },
24899 .anon_struct_type => |anon_struct| {
24900 if (anon_struct.names.len == 0) {
24901 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
24902 } else {
24903 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24904 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24905 }
2487124906 },
24907 else => unreachable,
2487224908 }
2487324909}
2487424910
......@@ -25931,7 +25967,7 @@ fn coerceExtra(
2593125967 .Union => {
2593225968 // pointer to anonymous struct to pointer to union
2593325969 if (inst_ty.isSinglePointer(mod) and
25934 inst_ty.childType(mod).isAnonStruct() and
25970 inst_ty.childType(mod).isAnonStruct(mod) and
2593525971 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2593625972 {
2593725973 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
......@@ -25940,7 +25976,7 @@ fn coerceExtra(
2594025976 .Struct => {
2594125977 // pointer to anonymous struct to pointer to struct
2594225978 if (inst_ty.isSinglePointer(mod) and
25943 inst_ty.childType(mod).isAnonStruct() and
25979 inst_ty.childType(mod).isAnonStruct(mod) and
2594425980 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2594525981 {
2594625982 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src) catch |err| switch (err) {
......@@ -26231,7 +26267,7 @@ fn coerceExtra(
2623126267 .Union => switch (inst_ty.zigTypeTag(mod)) {
2623226268 .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),
2623326269 .Struct => {
26234 if (inst_ty.isAnonStruct()) {
26270 if (inst_ty.isAnonStruct(mod)) {
2623526271 return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src);
2623626272 }
2623726273 },
......@@ -28771,8 +28807,8 @@ fn coerceAnonStructToUnion(
2877128807 return sema.failWithOwnedErrorMsg(msg);
2877228808 }
2877328809
28774 const anon_struct = inst_ty.castTag(.anon_struct).?.data;
28775 const field_name = anon_struct.names[0];
28810 const anon_struct = mod.intern_pool.indexToKey(inst_ty.ip_index).anon_struct_type;
28811 const field_name = mod.intern_pool.stringToSlice(anon_struct.names[0]);
2877628812 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
2877728813 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
2877828814}
......@@ -29010,13 +29046,14 @@ fn coerceTupleToStruct(
2901029046 @memset(field_refs, .none);
2901129047
2901229048 const inst_ty = sema.typeOf(inst);
29049 const anon_struct = mod.intern_pool.indexToKey(inst_ty.ip_index).anon_struct_type;
2901329050 var runtime_src: ?LazySrcLoc = null;
29014 const field_count = inst_ty.structFieldCount(mod);
29015 var field_i: u32 = 0;
29016 while (field_i < field_count) : (field_i += 1) {
29051 for (0..anon_struct.types.len) |field_index_usize| {
29052 const field_i = @intCast(u32, field_index_usize);
2901729053 const field_src = inst_src; // TODO better source location
29018 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|
29019 payload.data.names[field_i]
29054 const field_name = if (anon_struct.names.len != 0)
29055 // https://github.com/ziglang/zig/issues/15709
29056 @as([]const u8, mod.intern_pool.stringToSlice(anon_struct.names[field_i]))
2902029057 else
2902129058 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
2902229059 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
......@@ -29094,21 +29131,22 @@ fn coerceTupleToTuple(
2909429131 inst_src: LazySrcLoc,
2909529132) !Air.Inst.Ref {
2909629133 const mod = sema.mod;
29097 const dest_field_count = tuple_ty.structFieldCount(mod);
29098 const field_vals = try sema.arena.alloc(Value, dest_field_count);
29134 const dest_tuple = mod.intern_pool.indexToKey(tuple_ty.ip_index).anon_struct_type;
29135 const field_vals = try sema.arena.alloc(InternPool.Index, dest_tuple.types.len);
2909929136 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
2910029137 @memset(field_refs, .none);
2910129138
2910229139 const inst_ty = sema.typeOf(inst);
29103 const inst_field_count = inst_ty.structFieldCount(mod);
29104 if (inst_field_count > dest_field_count) return error.NotCoercible;
29140 const src_tuple = mod.intern_pool.indexToKey(inst_ty.ip_index).anon_struct_type;
29141 if (src_tuple.types.len > dest_tuple.types.len) return error.NotCoercible;
2910529142
2910629143 var runtime_src: ?LazySrcLoc = null;
29107 var field_i: u32 = 0;
29108 while (field_i < inst_field_count) : (field_i += 1) {
29144 for (dest_tuple.types, dest_tuple.values, 0..) |field_ty, default_val, field_index_usize| {
29145 const field_i = @intCast(u32, field_index_usize);
2910929146 const field_src = inst_src; // TODO better source location
29110 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|
29111 payload.data.names[field_i]
29147 const field_name = if (src_tuple.names.len != 0)
29148 // https://github.com/ziglang/zig/issues/15709
29149 @as([]const u8, mod.intern_pool.stringToSlice(src_tuple.names[field_i]))
2911229150 else
2911329151 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
2911429152
......@@ -29118,23 +29156,21 @@ fn coerceTupleToTuple(
2911829156
2911929157 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
2912029158
29121 const field_ty = tuple_ty.structFieldType(field_i, mod);
29122 const default_val = tuple_ty.structFieldDefaultValue(field_i, mod);
2912329159 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
29124 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
29160 const coerced = try sema.coerce(block, field_ty.toType(), elem_ref, field_src);
2912529161 field_refs[field_index] = coerced;
29126 if (default_val.ip_index != .unreachable_value) {
29162 if (default_val != .none) {
2912729163 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
2912829164 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
2912929165 };
2913029166
29131 if (!init_val.eql(default_val, field_ty, sema.mod)) {
29167 if (!init_val.eql(default_val.toValue(), field_ty.toType(), sema.mod)) {
2913229168 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
2913329169 }
2913429170 }
2913529171 if (runtime_src == null) {
2913629172 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {
29137 field_vals[field_index] = field_val;
29173 field_vals[field_index] = field_val.ip_index;
2913829174 } else {
2913929175 runtime_src = field_src;
2914029176 }
......@@ -29145,14 +29181,16 @@ fn coerceTupleToTuple(
2914529181 var root_msg: ?*Module.ErrorMsg = null;
2914629182 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
2914729183
29148 for (field_refs, 0..) |*field_ref, i| {
29184 for (
29185 dest_tuple.types,
29186 dest_tuple.values,
29187 field_refs,
29188 0..,
29189 ) |field_ty, default_val, *field_ref, i| {
2914929190 if (field_ref.* != .none) continue;
2915029191
29151 const default_val = tuple_ty.structFieldDefaultValue(i, mod);
29152 const field_ty = tuple_ty.structFieldType(i, mod);
29153
2915429192 const field_src = inst_src; // TODO better source location
29155 if (default_val.ip_index == .unreachable_value) {
29193 if (default_val == .none) {
2915629194 if (tuple_ty.isTuple(mod)) {
2915729195 const template = "missing tuple field: {d}";
2915829196 if (root_msg) |msg| {
......@@ -29174,7 +29212,7 @@ fn coerceTupleToTuple(
2917429212 if (runtime_src == null) {
2917529213 field_vals[i] = default_val;
2917629214 } else {
29177 field_ref.* = try sema.addConstant(field_ty, default_val);
29215 field_ref.* = try sema.addConstant(field_ty.toType(), default_val.toValue());
2917829216 }
2917929217 }
2918029218
......@@ -29191,7 +29229,10 @@ fn coerceTupleToTuple(
2919129229
2919229230 return sema.addConstant(
2919329231 tuple_ty,
29194 try Value.Tag.aggregate.create(sema.arena, field_vals),
29232 (try mod.intern(.{ .aggregate = .{
29233 .ty = tuple_ty.ip_index,
29234 .fields = field_vals,
29235 } })).toValue(),
2919529236 );
2919629237}
2919729238
......@@ -31591,17 +31632,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3159131632 return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));
3159231633 },
3159331634
31594 .tuple, .anon_struct => {
31595 const tuple = ty.tupleFields();
31596 for (tuple.types, 0..) |field_ty, i| {
31597 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
31598 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {
31599 return true;
31600 }
31601 }
31602 return false;
31603 },
31604
3160531635 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
3160631636 .anyframe_T => {
3160731637 const child_ty = ty.castTag(.anyframe_T).?.data;
......@@ -31690,6 +31720,16 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3169031720 }
3169131721 },
3169231722
31723 .anon_struct_type => |tuple| {
31724 for (tuple.types, tuple.values) |field_ty, field_val| {
31725 const have_comptime_val = field_val != .none;
31726 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty.toType())) {
31727 return true;
31728 }
31729 }
31730 return false;
31731 },
31732
3169331733 .union_type => |union_type| {
3169431734 const union_obj = mod.unionPtr(union_type.index);
3169531735 switch (union_obj.requires_comptime) {
......@@ -31740,20 +31780,16 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
3174031780 return sema.resolveTypeFully(child_ty);
3174131781 },
3174231782 .Struct => switch (ty.ip_index) {
31743 .none => switch (ty.tag()) {
31744 .tuple, .anon_struct => {
31745 const tuple = ty.tupleFields();
31746
31783 .none => {}, // TODO make this unreachable when all types are migrated to InternPool
31784 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31785 .struct_type => return sema.resolveStructFully(ty),
31786 .anon_struct_type => |tuple| {
3174731787 for (tuple.types) |field_ty| {
31748 try sema.resolveTypeFully(field_ty);
31788 try sema.resolveTypeFully(field_ty.toType());
3174931789 }
3175031790 },
3175131791 else => {},
3175231792 },
31753 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31754 .struct_type => return sema.resolveStructFully(ty),
31755 else => {},
31756 },
3175731793 },
3175831794 .Union => return sema.resolveUnionFully(ty),
3175931795 .Array => return sema.resolveTypeFully(ty.childType(mod)),
......@@ -33038,17 +33074,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3303833074 }
3303933075 },
3304033076
33041 .tuple, .anon_struct => {
33042 const tuple = ty.tupleFields();
33043 for (tuple.values, 0..) |val, i| {
33044 const is_comptime = val.ip_index != .unreachable_value;
33045 if (is_comptime) continue;
33046 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;
33047 return null;
33048 }
33049 return Value.empty_struct;
33050 },
33051
3305233077 .inferred_alloc_const => unreachable,
3305333078 .inferred_alloc_mut => unreachable,
3305433079 },
......@@ -33150,7 +33175,36 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3315033175 }
3315133176 }
3315233177 }
33153 // In this case the struct has no fields and therefore has one possible value.
33178 // In this case the struct has no runtime-known fields and
33179 // therefore has one possible value.
33180
33181 // TODO: this is incorrect for structs with comptime fields, I think
33182 // we should use a temporary allocator to construct an aggregate that
33183 // is populated with the comptime values and then intern that value here.
33184 // This TODO is repeated for anon_struct_type below, as well as
33185 // in the redundant implementation of one-possible-value in type.zig.
33186 const empty = try mod.intern(.{ .aggregate = .{
33187 .ty = ty.ip_index,
33188 .fields = &.{},
33189 } });
33190 return empty.toValue();
33191 },
33192
33193 .anon_struct_type => |tuple| {
33194 for (tuple.types, tuple.values) |field_ty, val| {
33195 const is_comptime = val != .none;
33196 if (is_comptime) continue;
33197 if ((try sema.typeHasOnePossibleValue(field_ty.toType())) != null) continue;
33198 return null;
33199 }
33200 // In this case the struct has no runtime-known fields and
33201 // therefore has one possible value.
33202
33203 // TODO: this is incorrect for structs with comptime fields, I think
33204 // we should use a temporary allocator to construct an aggregate that
33205 // is populated with the comptime values and then intern that value here.
33206 // This TODO is repeated for struct_type above, as well as
33207 // in the redundant implementation of one-possible-value in type.zig.
3315433208 const empty = try mod.intern(.{ .aggregate = .{
3315533209 .ty = ty.ip_index,
3315633210 .fields = &.{},
......@@ -33647,17 +33701,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3364733701 return sema.typeRequiresComptime(ty.optionalChild(mod));
3364833702 },
3364933703
33650 .tuple, .anon_struct => {
33651 const tuple = ty.tupleFields();
33652 for (tuple.types, 0..) |field_ty, i| {
33653 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
33654 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) {
33655 return true;
33656 }
33657 }
33658 return false;
33659 },
33660
3366133704 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
3366233705 .anyframe_T => {
3366333706 const child_ty = ty.castTag(.anyframe_T).?.data;
......@@ -33752,6 +33795,15 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3375233795 },
3375333796 }
3375433797 },
33798 .anon_struct_type => |tuple| {
33799 for (tuple.types, tuple.values) |field_ty, val| {
33800 const have_comptime_val = val != .none;
33801 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty.toType())) {
33802 return true;
33803 }
33804 }
33805 return false;
33806 },
3375533807
3375633808 .union_type => |union_type| {
3375733809 const union_obj = mod.unionPtr(union_type.index);
......@@ -33865,7 +33917,7 @@ fn structFieldIndex(
3386533917) !u32 {
3386633918 const mod = sema.mod;
3386733919 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
33868 if (struct_ty.isAnonStruct()) {
33920 if (struct_ty.isAnonStruct(mod)) {
3386933921 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
3387033922 } else {
3387133923 const struct_obj = mod.typeToStruct(struct_ty).?;
......@@ -33882,9 +33934,10 @@ fn anonStructFieldIndex(
3388233934 field_name: []const u8,
3388333935 field_src: LazySrcLoc,
3388433936) !u32 {
33885 const anon_struct = struct_ty.castTag(.anon_struct).?.data;
33937 const mod = sema.mod;
33938 const anon_struct = mod.intern_pool.indexToKey(struct_ty.ip_index).anon_struct_type;
3388633939 for (anon_struct.names, 0..) |name, i| {
33887 if (mem.eql(u8, name, field_name)) {
33940 if (mem.eql(u8, mod.intern_pool.stringToSlice(name), field_name)) {
3388833941 return @intCast(u32, i);
3388933942 }
3389033943 }
src/TypedValue.zig+10-10
......@@ -177,13 +177,16 @@ pub fn print(
177177 }
178178
179179 if (field_ptr.container_ty.zigTypeTag(mod) == .Struct) {
180 switch (field_ptr.container_ty.tag()) {
181 .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}),
182 else => {
183 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index, mod);
184 return writer.print(".{s}", .{field_name});
180 switch (mod.intern_pool.indexToKey(field_ptr.container_ty.ip_index)) {
181 .anon_struct_type => |anon_struct| {
182 if (anon_struct.names.len == 0) {
183 return writer.print(".@\"{d}\"", .{field_ptr.field_index});
184 }
185185 },
186 else => {},
186187 }
188 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index, mod);
189 return writer.print(".{s}", .{field_name});
187190 } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) {
188191 const field_name = field_ptr.container_ty.unionFields(mod).keys()[field_ptr.field_index];
189192 return writer.print(".{s}", .{field_name});
......@@ -396,12 +399,9 @@ fn printAggregate(
396399 while (i < max_len) : (i += 1) {
397400 if (i != 0) try writer.writeAll(", ");
398401 switch (ty.ip_index) {
399 .none => switch (ty.tag()) {
400 .anon_struct => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
401 else => {},
402 },
402 .none => {}, // TODO make this unreachable after finishing InternPool migration
403403 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
404 .struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
404 .struct_type, .anon_struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
405405 else => {},
406406 },
407407 }
src/arch/x86_64/CodeGen.zig+1-1
......@@ -11411,7 +11411,7 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
1141111411 const union_obj = mod.typeToUnion(union_ty).?;
1141211412 const field_name = union_obj.fields.keys()[extra.field_index];
1141311413 const tag_ty = union_obj.tag_ty;
11414 const field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);
11414 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
1141511415 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
1141611416 const tag_int_val = try tag_val.enumToInt(tag_ty, mod);
1141711417 const tag_int = tag_int_val.toUnsignedInt(mod);
src/codegen/c.zig+25-31
......@@ -3417,8 +3417,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
34173417 const op_inst = Air.refToIndex(un_op);
34183418 const op_ty = f.typeOf(un_op);
34193419 const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty;
3420 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
3421 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, mod);
3420 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
34223421
34233422 if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) {
34243423 try reap(f, inst, &.{un_op});
......@@ -4115,8 +4114,7 @@ fn airCall(
41154114 }
41164115 resolved_arg.* = try f.resolveInst(arg);
41174116 if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {
4118 var lowered_arg_buf: LowerFnRetTyBuffer = undefined;
4119 const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, mod);
4117 const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod);
41204118
41214119 const array_local = try f.allocLocal(inst, lowered_arg_ty);
41224120 try writer.writeAll("memcpy(");
......@@ -4146,8 +4144,7 @@ fn airCall(
41464144 };
41474145
41484146 const ret_ty = fn_ty.fnReturnType();
4149 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
4150 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, mod);
4147 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
41514148
41524149 const result_local = result: {
41534150 if (modifier == .always_tail) {
......@@ -5200,7 +5197,7 @@ fn fieldLocation(
52005197 const field_ty = container_ty.structFieldType(next_field_index, mod);
52015198 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
52025199
5203 break .{ .field = if (container_ty.isSimpleTuple())
5200 break .{ .field = if (container_ty.isSimpleTuple(mod))
52045201 .{ .field = next_field_index }
52055202 else
52065203 .{ .identifier = container_ty.structFieldName(next_field_index, mod) } };
......@@ -5395,16 +5392,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
53955392
53965393 const field_name: CValue = switch (struct_ty.ip_index) {
53975394 .none => switch (struct_ty.tag()) {
5398 .tuple, .anon_struct => if (struct_ty.isSimpleTuple())
5399 .{ .field = extra.field_index }
5400 else
5401 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5402
54035395 else => unreachable,
54045396 },
54055397 else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
54065398 .struct_type => switch (struct_ty.containerLayout(mod)) {
5407 .Auto, .Extern => if (struct_ty.isSimpleTuple())
5399 .Auto, .Extern => if (struct_ty.isSimpleTuple(mod))
54085400 .{ .field = extra.field_index }
54095401 else
54105402 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
......@@ -5465,6 +5457,12 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
54655457 return local;
54665458 },
54675459 },
5460
5461 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)
5462 .{ .field = extra.field_index }
5463 else
5464 .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) },
5465
54685466 .union_type => |union_type| field_name: {
54695467 const union_obj = mod.unionPtr(union_type.index);
54705468 if (union_obj.layout == .Packed) {
......@@ -6791,7 +6789,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
67916789 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
67926790
67936791 const a = try Assignment.start(f, writer, field_ty);
6794 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple())
6792 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod))
67956793 .{ .field = field_i }
67966794 else
67976795 .{ .identifier = inst_ty.structFieldName(field_i, mod) });
......@@ -7704,25 +7702,21 @@ const Vectorize = struct {
77047702 }
77057703};
77067704
7707const LowerFnRetTyBuffer = struct {
7708 names: [1][]const u8,
7709 types: [1]Type,
7710 values: [1]Value,
7711 payload: Type.Payload.AnonStruct,
7712};
7713fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *Module) Type {
7714 if (ret_ty.zigTypeTag(mod) == .NoReturn) return Type.noreturn;
7705fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
7706 if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;
77157707
77167708 if (lowersToArray(ret_ty, mod)) {
7717 buffer.names = [1][]const u8{"array"};
7718 buffer.types = [1]Type{ret_ty};
7719 buffer.values = [1]Value{Value.@"unreachable"};
7720 buffer.payload = .{ .data = .{
7721 .names = &buffer.names,
7722 .types = &buffer.types,
7723 .values = &buffer.values,
7724 } };
7725 return Type.initPayload(&buffer.payload.base);
7709 const names = [1]InternPool.NullTerminatedString{
7710 try mod.intern_pool.getOrPutString(mod.gpa, "array"),
7711 };
7712 const types = [1]InternPool.Index{ret_ty.ip_index};
7713 const values = [1]InternPool.Index{.none};
7714 const interned = try mod.intern(.{ .anon_struct_type = .{
7715 .names = &names,
7716 .types = &types,
7717 .values = &values,
7718 } });
7719 return interned.toType();
77267720 }
77277721
77287722 return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void;
src/codegen/c/type.zig+3-3
......@@ -1951,7 +1951,7 @@ pub const CType = extern union {
19511951
19521952 defer c_field_i += 1;
19531953 fields_pl[c_field_i] = .{
1954 .name = try if (ty.isSimpleTuple())
1954 .name = try if (ty.isSimpleTuple(mod))
19551955 std.fmt.allocPrintZ(arena, "f{}", .{field_i})
19561956 else
19571957 arena.dupeZ(u8, switch (zig_ty_tag) {
......@@ -2102,7 +2102,7 @@ pub const CType = extern union {
21022102 .payload => unreachable,
21032103 }) or !mem.eql(
21042104 u8,
2105 if (ty.isSimpleTuple())
2105 if (ty.isSimpleTuple(mod))
21062106 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
21072107 else switch (zig_ty_tag) {
21082108 .Struct => ty.structFieldName(field_i, mod),
......@@ -2224,7 +2224,7 @@ pub const CType = extern union {
22242224 .global => .global,
22252225 .payload => unreachable,
22262226 });
2227 hasher.update(if (ty.isSimpleTuple())
2227 hasher.update(if (ty.isSimpleTuple(mod))
22282228 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
22292229 else switch (zig_ty_tag) {
22302230 .Struct => ty.structFieldName(field_i, mod),
src/codegen/llvm.zig+263-255
......@@ -2009,83 +2009,84 @@ pub const Object = struct {
20092009 break :blk fwd_decl;
20102010 };
20112011
2012 if (ty.isSimpleTupleOrAnonStruct()) {
2013 const tuple = ty.tupleFields();
2014
2015 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2016 defer di_fields.deinit(gpa);
2017
2018 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
2019
2020 comptime assert(struct_layout_version == 2);
2021 var offset: u64 = 0;
2022
2023 for (tuple.types, 0..) |field_ty, i| {
2024 const field_val = tuple.values[i];
2025 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue;
2026
2027 const field_size = field_ty.abiSize(mod);
2028 const field_align = field_ty.abiAlignment(mod);
2029 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2030 offset = field_offset + field_size;
2031
2032 const field_name = if (ty.castTag(.anon_struct)) |payload|
2033 try gpa.dupeZ(u8, payload.data.names[i])
2034 else
2035 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2036 defer gpa.free(field_name);
2012 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2013 .anon_struct_type => |tuple| {
2014 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2015 defer di_fields.deinit(gpa);
2016
2017 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
2018
2019 comptime assert(struct_layout_version == 2);
2020 var offset: u64 = 0;
2021
2022 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
2023 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
2024
2025 const field_size = field_ty.toType().abiSize(mod);
2026 const field_align = field_ty.toType().abiAlignment(mod);
2027 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2028 offset = field_offset + field_size;
2029
2030 const field_name = if (tuple.names.len != 0)
2031 mod.intern_pool.stringToSlice(tuple.names[i])
2032 else
2033 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2034 defer gpa.free(field_name);
2035
2036 try di_fields.append(gpa, dib.createMemberType(
2037 fwd_decl.toScope(),
2038 field_name,
2039 null, // file
2040 0, // line
2041 field_size * 8, // size in bits
2042 field_align * 8, // align in bits
2043 field_offset * 8, // offset in bits
2044 0, // flags
2045 try o.lowerDebugType(field_ty.toType(), .full),
2046 ));
2047 }
20372048
2038 try di_fields.append(gpa, dib.createMemberType(
2039 fwd_decl.toScope(),
2040 field_name,
2049 const full_di_ty = dib.createStructType(
2050 compile_unit_scope,
2051 name.ptr,
20412052 null, // file
20422053 0, // line
2043 field_size * 8, // size in bits
2044 field_align * 8, // align in bits
2045 field_offset * 8, // offset in bits
2054 ty.abiSize(mod) * 8, // size in bits
2055 ty.abiAlignment(mod) * 8, // align in bits
20462056 0, // flags
2047 try o.lowerDebugType(field_ty, .full),
2048 ));
2049 }
2050
2051 const full_di_ty = dib.createStructType(
2052 compile_unit_scope,
2053 name.ptr,
2054 null, // file
2055 0, // line
2056 ty.abiSize(mod) * 8, // size in bits
2057 ty.abiAlignment(mod) * 8, // align in bits
2058 0, // flags
2059 null, // derived from
2060 di_fields.items.ptr,
2061 @intCast(c_int, di_fields.items.len),
2062 0, // run time lang
2063 null, // vtable holder
2064 "", // unique id
2065 );
2066 dib.replaceTemporary(fwd_decl, full_di_ty);
2067 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2068 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
2069 return full_di_ty;
2070 }
2071
2072 if (mod.typeToStruct(ty)) |struct_obj| {
2073 if (!struct_obj.haveFieldTypes()) {
2074 // This can happen if a struct type makes it all the way to
2075 // flush() without ever being instantiated or referenced (even
2076 // via pointer). The only reason we are hearing about it now is
2077 // that it is being used as a namespace to put other debug types
2078 // into. Therefore we can satisfy this by making an empty namespace,
2079 // rather than changing the frontend to unnecessarily resolve the
2080 // struct field types.
2081 const owner_decl_index = ty.getOwnerDecl(mod);
2082 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2083 dib.replaceTemporary(fwd_decl, struct_di_ty);
2084 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2085 // means we can't use `gop` anymore.
2086 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
2087 return struct_di_ty;
2088 }
2057 null, // derived from
2058 di_fields.items.ptr,
2059 @intCast(c_int, di_fields.items.len),
2060 0, // run time lang
2061 null, // vtable holder
2062 "", // unique id
2063 );
2064 dib.replaceTemporary(fwd_decl, full_di_ty);
2065 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2066 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
2067 return full_di_ty;
2068 },
2069 .struct_type => |struct_type| s: {
2070 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
2071
2072 if (!struct_obj.haveFieldTypes()) {
2073 // This can happen if a struct type makes it all the way to
2074 // flush() without ever being instantiated or referenced (even
2075 // via pointer). The only reason we are hearing about it now is
2076 // that it is being used as a namespace to put other debug types
2077 // into. Therefore we can satisfy this by making an empty namespace,
2078 // rather than changing the frontend to unnecessarily resolve the
2079 // struct field types.
2080 const owner_decl_index = ty.getOwnerDecl(mod);
2081 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2082 dib.replaceTemporary(fwd_decl, struct_di_ty);
2083 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2084 // means we can't use `gop` anymore.
2085 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
2086 return struct_di_ty;
2087 }
2088 },
2089 else => {},
20892090 }
20902091
20912092 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
......@@ -2931,59 +2932,61 @@ pub const DeclGen = struct {
29312932 // reference, we need to copy it here.
29322933 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
29332934
2934 if (t.isSimpleTupleOrAnonStruct()) {
2935 const tuple = t.tupleFields();
2936 const llvm_struct_ty = dg.context.structCreateNamed("");
2937 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2935 const struct_type = switch (mod.intern_pool.indexToKey(t.ip_index)) {
2936 .anon_struct_type => |tuple| {
2937 const llvm_struct_ty = dg.context.structCreateNamed("");
2938 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
29382939
2939 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
2940 defer llvm_field_types.deinit(gpa);
2940 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
2941 defer llvm_field_types.deinit(gpa);
29412942
2942 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
2943 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
29432944
2944 comptime assert(struct_layout_version == 2);
2945 var offset: u64 = 0;
2946 var big_align: u32 = 0;
2945 comptime assert(struct_layout_version == 2);
2946 var offset: u64 = 0;
2947 var big_align: u32 = 0;
29472948
2948 for (tuple.types, 0..) |field_ty, i| {
2949 const field_val = tuple.values[i];
2950 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue;
2949 for (tuple.types, tuple.values) |field_ty, field_val| {
2950 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
29512951
2952 const field_align = field_ty.abiAlignment(mod);
2953 big_align = @max(big_align, field_align);
2954 const prev_offset = offset;
2955 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2952 const field_align = field_ty.toType().abiAlignment(mod);
2953 big_align = @max(big_align, field_align);
2954 const prev_offset = offset;
2955 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
29562956
2957 const padding_len = offset - prev_offset;
2958 if (padding_len > 0) {
2959 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2960 try llvm_field_types.append(gpa, llvm_array_ty);
2961 }
2962 const field_llvm_ty = try dg.lowerType(field_ty);
2963 try llvm_field_types.append(gpa, field_llvm_ty);
2957 const padding_len = offset - prev_offset;
2958 if (padding_len > 0) {
2959 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2960 try llvm_field_types.append(gpa, llvm_array_ty);
2961 }
2962 const field_llvm_ty = try dg.lowerType(field_ty.toType());
2963 try llvm_field_types.append(gpa, field_llvm_ty);
29642964
2965 offset += field_ty.abiSize(mod);
2966 }
2967 {
2968 const prev_offset = offset;
2969 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2970 const padding_len = offset - prev_offset;
2971 if (padding_len > 0) {
2972 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2973 try llvm_field_types.append(gpa, llvm_array_ty);
2965 offset += field_ty.toType().abiSize(mod);
2966 }
2967 {
2968 const prev_offset = offset;
2969 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2970 const padding_len = offset - prev_offset;
2971 if (padding_len > 0) {
2972 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2973 try llvm_field_types.append(gpa, llvm_array_ty);
2974 }
29742975 }
2975 }
29762976
2977 llvm_struct_ty.structSetBody(
2978 llvm_field_types.items.ptr,
2979 @intCast(c_uint, llvm_field_types.items.len),
2980 .False,
2981 );
2977 llvm_struct_ty.structSetBody(
2978 llvm_field_types.items.ptr,
2979 @intCast(c_uint, llvm_field_types.items.len),
2980 .False,
2981 );
29822982
2983 return llvm_struct_ty;
2984 }
2983 return llvm_struct_ty;
2984 },
2985 .struct_type => |struct_type| struct_type,
2986 else => unreachable,
2987 };
29852988
2986 const struct_obj = mod.typeToStruct(t).?;
2989 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
29872990
29882991 if (struct_obj.layout == .Packed) {
29892992 assert(struct_obj.haveLayout());
......@@ -3625,71 +3628,74 @@ pub const DeclGen = struct {
36253628 const field_vals = tv.val.castTag(.aggregate).?.data;
36263629 const gpa = dg.gpa;
36273630
3628 if (tv.ty.isSimpleTupleOrAnonStruct()) {
3629 const tuple = tv.ty.tupleFields();
3630 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3631 defer llvm_fields.deinit(gpa);
3631 const struct_type = switch (mod.intern_pool.indexToKey(tv.ty.ip_index)) {
3632 .anon_struct_type => |tuple| {
3633 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3634 defer llvm_fields.deinit(gpa);
36323635
3633 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
3636 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
36343637
3635 comptime assert(struct_layout_version == 2);
3636 var offset: u64 = 0;
3637 var big_align: u32 = 0;
3638 var need_unnamed = false;
3638 comptime assert(struct_layout_version == 2);
3639 var offset: u64 = 0;
3640 var big_align: u32 = 0;
3641 var need_unnamed = false;
36393642
3640 for (tuple.types, 0..) |field_ty, i| {
3641 if (tuple.values[i].ip_index != .unreachable_value) continue;
3642 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
3643
3644 const field_align = field_ty.abiAlignment(mod);
3645 big_align = @max(big_align, field_align);
3646 const prev_offset = offset;
3647 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3648
3649 const padding_len = offset - prev_offset;
3650 if (padding_len > 0) {
3651 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3652 // TODO make this and all other padding elsewhere in debug
3653 // builds be 0xaa not undef.
3654 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3655 }
3643 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3644 if (field_val != .none) continue;
3645 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
36563646
3657 const field_llvm_val = try dg.lowerValue(.{
3658 .ty = field_ty,
3659 .val = field_vals[i],
3660 });
3647 const field_align = field_ty.toType().abiAlignment(mod);
3648 big_align = @max(big_align, field_align);
3649 const prev_offset = offset;
3650 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
36613651
3662 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field_llvm_val);
3652 const padding_len = offset - prev_offset;
3653 if (padding_len > 0) {
3654 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3655 // TODO make this and all other padding elsewhere in debug
3656 // builds be 0xaa not undef.
3657 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3658 }
36633659
3664 llvm_fields.appendAssumeCapacity(field_llvm_val);
3660 const field_llvm_val = try dg.lowerValue(.{
3661 .ty = field_ty.toType(),
3662 .val = field_vals[i],
3663 });
36653664
3666 offset += field_ty.abiSize(mod);
3667 }
3668 {
3669 const prev_offset = offset;
3670 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3671 const padding_len = offset - prev_offset;
3672 if (padding_len > 0) {
3673 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3674 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3665 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val);
3666
3667 llvm_fields.appendAssumeCapacity(field_llvm_val);
3668
3669 offset += field_ty.toType().abiSize(mod);
3670 }
3671 {
3672 const prev_offset = offset;
3673 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3674 const padding_len = offset - prev_offset;
3675 if (padding_len > 0) {
3676 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3677 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3678 }
36753679 }
3676 }
36773680
3678 if (need_unnamed) {
3679 return dg.context.constStruct(
3680 llvm_fields.items.ptr,
3681 @intCast(c_uint, llvm_fields.items.len),
3682 .False,
3683 );
3684 } else {
3685 return llvm_struct_ty.constNamedStruct(
3686 llvm_fields.items.ptr,
3687 @intCast(c_uint, llvm_fields.items.len),
3688 );
3689 }
3690 }
3681 if (need_unnamed) {
3682 return dg.context.constStruct(
3683 llvm_fields.items.ptr,
3684 @intCast(c_uint, llvm_fields.items.len),
3685 .False,
3686 );
3687 } else {
3688 return llvm_struct_ty.constNamedStruct(
3689 llvm_fields.items.ptr,
3690 @intCast(c_uint, llvm_fields.items.len),
3691 );
3692 }
3693 },
3694 .struct_type => |struct_type| struct_type,
3695 else => unreachable,
3696 };
36913697
3692 const struct_obj = mod.typeToStruct(tv.ty).?;
3698 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
36933699
36943700 if (struct_obj.layout == .Packed) {
36953701 assert(struct_obj.haveLayout());
......@@ -4077,13 +4083,11 @@ pub const DeclGen = struct {
40774083 return field_addr.constIntToPtr(final_llvm_ty);
40784084 }
40794085
4080 var ty_buf: Type.Payload.Pointer = undefined;
4081
40824086 const parent_llvm_ty = try dg.lowerType(parent_ty);
4083 if (llvmFieldIndex(parent_ty, field_index, mod, &ty_buf)) |llvm_field_index| {
4087 if (llvmField(parent_ty, field_index, mod)) |llvm_field| {
40844088 const indices: [2]*llvm.Value = .{
40854089 llvm_u32.constInt(0, .False),
4086 llvm_u32.constInt(llvm_field_index, .False),
4090 llvm_u32.constInt(llvm_field.index, .False),
40874091 };
40884092 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
40894093 } else {
......@@ -6006,8 +6010,7 @@ pub const FuncGen = struct {
60066010 return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");
60076011 },
60086012 else => {
6009 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6010 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;
6013 const llvm_field_index = llvmField(struct_ty, field_index, mod).?.index;
60116014 return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, "");
60126015 },
60136016 },
......@@ -6035,16 +6038,22 @@ pub const FuncGen = struct {
60356038 switch (struct_ty.zigTypeTag(mod)) {
60366039 .Struct => {
60376040 assert(struct_ty.containerLayout(mod) != .Packed);
6038 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6039 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;
6041 const llvm_field = llvmField(struct_ty, field_index, mod).?;
60406042 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6041 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, "");
6042 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);
6043 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, "");
6044 const field_ptr_ty = try mod.ptrType(.{
6045 .elem_type = llvm_field.ty.ip_index,
6046 .alignment = llvm_field.alignment,
6047 });
60436048 if (isByRef(field_ty, mod)) {
60446049 if (canElideLoad(self, body_tail))
60456050 return field_ptr;
60466051
6047 return self.loadByRef(field_ptr, field_ty, ptr_ty_buf.data.alignment(mod), false);
6052 const field_alignment = if (llvm_field.alignment != 0)
6053 llvm_field.alignment
6054 else
6055 llvm_field.ty.abiAlignment(mod);
6056 return self.loadByRef(field_ptr, field_ty, field_alignment, false);
60486057 } else {
60496058 return self.load(field_ptr, field_ptr_ty);
60506059 }
......@@ -6912,12 +6921,14 @@ pub const FuncGen = struct {
69126921 const struct_ty = self.air.getRefType(ty_pl.ty);
69136922 const field_index = ty_pl.payload;
69146923
6915 var ptr_ty_buf: Type.Payload.Pointer = undefined;
69166924 const mod = self.dg.module;
6917 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, mod, &ptr_ty_buf).?;
6925 const llvm_field = llvmField(struct_ty, field_index, mod).?;
69186926 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6919 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, "");
6920 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);
6927 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, "");
6928 const field_ptr_ty = try mod.ptrType(.{
6929 .elem_type = llvm_field.ty.ip_index,
6930 .alignment = llvm_field.alignment,
6931 });
69216932 return self.load(field_ptr, field_ptr_ty);
69226933 }
69236934
......@@ -7430,9 +7441,8 @@ pub const FuncGen = struct {
74307441 const result = self.builder.buildExtractValue(result_struct, 0, "");
74317442 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");
74327443
7433 var ty_buf: Type.Payload.Pointer = undefined;
7434 const result_index = llvmFieldIndex(dest_ty, 0, mod, &ty_buf).?;
7435 const overflow_index = llvmFieldIndex(dest_ty, 1, mod, &ty_buf).?;
7444 const result_index = llvmField(dest_ty, 0, mod).?.index;
7445 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
74367446
74377447 if (isByRef(dest_ty, mod)) {
74387448 const result_alignment = dest_ty.abiAlignment(mod);
......@@ -7736,9 +7746,8 @@ pub const FuncGen = struct {
77367746
77377747 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");
77387748
7739 var ty_buf: Type.Payload.Pointer = undefined;
7740 const result_index = llvmFieldIndex(dest_ty, 0, mod, &ty_buf).?;
7741 const overflow_index = llvmFieldIndex(dest_ty, 1, mod, &ty_buf).?;
7749 const result_index = llvmField(dest_ty, 0, mod).?.index;
7750 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
77427751
77437752 if (isByRef(dest_ty, mod)) {
77447753 const result_alignment = dest_ty.abiAlignment(mod);
......@@ -9300,8 +9309,6 @@ pub const FuncGen = struct {
93009309 return running_int;
93019310 }
93029311
9303 var ptr_ty_buf: Type.Payload.Pointer = undefined;
9304
93059312 if (isByRef(result_ty, mod)) {
93069313 const llvm_u32 = self.context.intType(32);
93079314 // TODO in debug builds init to undef so that the padding will be 0xaa
......@@ -9313,7 +9320,7 @@ pub const FuncGen = struct {
93139320 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93149321
93159322 const llvm_elem = try self.resolveInst(elem);
9316 const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;
9323 const llvm_i = llvmField(result_ty, i, mod).?.index;
93179324 indices[1] = llvm_u32.constInt(llvm_i, .False);
93189325 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
93199326 var field_ptr_payload: Type.Payload.Pointer = .{
......@@ -9334,7 +9341,7 @@ pub const FuncGen = struct {
93349341 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93359342
93369343 const llvm_elem = try self.resolveInst(elem);
9337 const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;
9344 const llvm_i = llvmField(result_ty, i, mod).?.index;
93389345 result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, "");
93399346 }
93409347 return result;
......@@ -9796,9 +9803,8 @@ pub const FuncGen = struct {
97969803 else => {
97979804 const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty);
97989805
9799 var ty_buf: Type.Payload.Pointer = undefined;
9800 if (llvmFieldIndex(struct_ty, field_index, mod, &ty_buf)) |llvm_field_index| {
9801 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, "");
9806 if (llvmField(struct_ty, field_index, mod)) |llvm_field| {
9807 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field.index, "");
98029808 } else {
98039809 // If we found no index then this means this is a zero sized field at the
98049810 // end of the struct. Treat our struct pointer as an array of two and get
......@@ -10457,59 +10463,61 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ
1045710463 };
1045810464}
1045910465
10466const LlvmField = struct {
10467 index: c_uint,
10468 ty: Type,
10469 alignment: u32,
10470};
10471
1046010472/// Take into account 0 bit fields and padding. Returns null if an llvm
1046110473/// field could not be found.
1046210474/// This only happens if you want the field index of a zero sized field at
1046310475/// the end of the struct.
10464fn llvmFieldIndex(
10465 ty: Type,
10466 field_index: usize,
10467 mod: *Module,
10468 ptr_pl_buf: *Type.Payload.Pointer,
10469) ?c_uint {
10476fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
1047010477 // Detects where we inserted extra padding fields so that we can skip
1047110478 // over them in this function.
1047210479 comptime assert(struct_layout_version == 2);
1047310480 var offset: u64 = 0;
1047410481 var big_align: u32 = 0;
1047510482
10476 if (ty.isSimpleTupleOrAnonStruct()) {
10477 const tuple = ty.tupleFields();
10478 var llvm_field_index: c_uint = 0;
10479 for (tuple.types, 0..) |field_ty, i| {
10480 if (tuple.values[i].ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue;
10483 const struct_type = switch (mod.intern_pool.indexToKey(ty.ip_index)) {
10484 .anon_struct_type => |tuple| {
10485 var llvm_field_index: c_uint = 0;
10486 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
10487 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1048110488
10482 const field_align = field_ty.abiAlignment(mod);
10483 big_align = @max(big_align, field_align);
10484 const prev_offset = offset;
10485 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
10489 const field_align = field_ty.toType().abiAlignment(mod);
10490 big_align = @max(big_align, field_align);
10491 const prev_offset = offset;
10492 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1048610493
10487 const padding_len = offset - prev_offset;
10488 if (padding_len > 0) {
10489 llvm_field_index += 1;
10490 }
10494 const padding_len = offset - prev_offset;
10495 if (padding_len > 0) {
10496 llvm_field_index += 1;
10497 }
1049110498
10492 if (field_index <= i) {
10493 ptr_pl_buf.* = .{
10494 .data = .{
10495 .pointee_type = field_ty,
10496 .@"align" = field_align,
10497 .@"addrspace" = .generic,
10498 },
10499 };
10500 return llvm_field_index;
10501 }
10499 if (field_index <= i) {
10500 return .{
10501 .index = llvm_field_index,
10502 .ty = field_ty.toType(),
10503 .alignment = field_align,
10504 };
10505 }
1050210506
10503 llvm_field_index += 1;
10504 offset += field_ty.abiSize(mod);
10505 }
10506 return null;
10507 }
10508 const layout = ty.containerLayout(mod);
10507 llvm_field_index += 1;
10508 offset += field_ty.toType().abiSize(mod);
10509 }
10510 return null;
10511 },
10512 .struct_type => |s| s,
10513 else => unreachable,
10514 };
10515 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
10516 const layout = struct_obj.layout;
1050910517 assert(layout != .Packed);
1051010518
1051110519 var llvm_field_index: c_uint = 0;
10512 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);
10520 var it = struct_obj.runtimeFieldIterator(mod);
1051310521 while (it.next()) |field_and_index| {
1051410522 const field = field_and_index.field;
1051510523 const field_align = field.alignment(mod, layout);
......@@ -10523,14 +10531,11 @@ fn llvmFieldIndex(
1052310531 }
1052410532
1052510533 if (field_index == field_and_index.index) {
10526 ptr_pl_buf.* = .{
10527 .data = .{
10528 .pointee_type = field.ty,
10529 .@"align" = field_align,
10530 .@"addrspace" = .generic,
10531 },
10534 return .{
10535 .index = llvm_field_index,
10536 .ty = field.ty,
10537 .alignment = field_align,
1053210538 };
10533 return llvm_field_index;
1053410539 }
1053510540
1053610541 llvm_field_index += 1;
......@@ -11089,21 +11094,24 @@ fn isByRef(ty: Type, mod: *Module) bool {
1108911094 .Struct => {
1109011095 // Packed structs are represented to LLVM as integers.
1109111096 if (ty.containerLayout(mod) == .Packed) return false;
11092 if (ty.isSimpleTupleOrAnonStruct()) {
11093 const tuple = ty.tupleFields();
11094 var count: usize = 0;
11095 for (tuple.values, 0..) |field_val, i| {
11096 if (field_val.ip_index != .unreachable_value or !tuple.types[i].hasRuntimeBits(mod)) continue;
11097
11098 count += 1;
11099 if (count > max_fields_byval) return true;
11100 if (isByRef(tuple.types[i], mod)) return true;
11101 }
11102 return false;
11103 }
11097 const struct_type = switch (mod.intern_pool.indexToKey(ty.ip_index)) {
11098 .anon_struct_type => |tuple| {
11099 var count: usize = 0;
11100 for (tuple.types, tuple.values) |field_ty, field_val| {
11101 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
11102
11103 count += 1;
11104 if (count > max_fields_byval) return true;
11105 if (isByRef(field_ty.toType(), mod)) return true;
11106 }
11107 return false;
11108 },
11109 .struct_type => |s| s,
11110 else => unreachable,
11111 };
11112 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1110411113 var count: usize = 0;
11105 const fields = ty.structFields(mod);
11106 for (fields.values()) |field| {
11114 for (struct_obj.fields.values()) |field| {
1110711115 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
1110811116
1110911117 count += 1;
src/codegen/spirv.zig+6-5
......@@ -682,7 +682,7 @@ pub const DeclGen = struct {
682682 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
683683 },
684684 .Struct => {
685 if (ty.isSimpleTupleOrAnonStruct()) {
685 if (ty.isSimpleTupleOrAnonStruct(mod)) {
686686 unreachable; // TODO
687687 } else {
688688 const struct_ty = mod.typeToStruct(ty).?;
......@@ -1319,7 +1319,8 @@ pub const DeclGen = struct {
13191319 defer self.gpa.free(member_names);
13201320
13211321 var member_index: usize = 0;
1322 for (struct_ty.fields.values(), 0..) |field, i| {
1322 const struct_obj = void; // TODO
1323 for (struct_obj.fields.values(), 0..) |field, i| {
13231324 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
13241325
13251326 member_types[member_index] = try self.resolveType(field.ty, .indirect);
......@@ -1327,7 +1328,7 @@ pub const DeclGen = struct {
13271328 member_index += 1;
13281329 }
13291330
1330 const name = try struct_ty.getFullyQualifiedName(self.module);
1331 const name = try struct_obj.getFullyQualifiedName(self.module);
13311332 defer self.module.gpa.free(name);
13321333
13331334 return try self.spv.resolve(.{ .struct_type = .{
......@@ -2090,7 +2091,7 @@ pub const DeclGen = struct {
20902091
20912092 var i: usize = 0;
20922093 while (i < mask_len) : (i += 1) {
2093 const elem = try mask.elemValue(self.module, i);
2094 const elem = try mask.elemValue(mod, i);
20942095 if (elem.isUndef(mod)) {
20952096 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);
20962097 } else {
......@@ -2805,7 +2806,7 @@ pub const DeclGen = struct {
28052806 const value = try self.resolve(bin_op.rhs);
28062807 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
28072808
2808 const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;
2809 const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
28092810 if (val_is_undef) {
28102811 const undef = try self.spv.constUndef(ptr_ty_ref);
28112812 try self.store(ptr_ty, ptr, undef);
src/link/Dwarf.zig+12-10
......@@ -333,13 +333,12 @@ pub const DeclState = struct {
333333 // DW.AT.byte_size, DW.FORM.udata
334334 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
335335
336 switch (ty.tag()) {
337 .tuple, .anon_struct => {
336 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
337 .anon_struct_type => |fields| {
338338 // DW.AT.name, DW.FORM.string
339339 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
340340
341 const fields = ty.tupleFields();
342 for (fields.types, 0..) |field, field_index| {
341 for (fields.types, 0..) |field_ty, field_index| {
343342 // DW.AT.member
344343 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
345344 // DW.AT.name, DW.FORM.string
......@@ -347,28 +346,30 @@ pub const DeclState = struct {
347346 // DW.AT.type, DW.FORM.ref4
348347 var index = dbg_info_buffer.items.len;
349348 try dbg_info_buffer.resize(index + 4);
350 try self.addTypeRelocGlobal(atom_index, field, @intCast(u32, index));
349 try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(u32, index));
351350 // DW.AT.data_member_location, DW.FORM.udata
352351 const field_off = ty.structFieldOffset(field_index, mod);
353352 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
354353 }
355354 },
356 else => {
355 .struct_type => |struct_type| s: {
356 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
357357 // DW.AT.name, DW.FORM.string
358358 const struct_name = try ty.nameAllocArena(arena, mod);
359359 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);
360360 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
361361 dbg_info_buffer.appendAssumeCapacity(0);
362362
363 const struct_obj = mod.typeToStruct(ty).?;
364363 if (struct_obj.layout == .Packed) {
365364 log.debug("TODO implement .debug_info for packed structs", .{});
366365 break :blk;
367366 }
368367
369 const fields = ty.structFields(mod);
370 for (fields.keys(), 0..) |field_name, field_index| {
371 const field = fields.get(field_name).?;
368 for (
369 struct_obj.fields.keys(),
370 struct_obj.fields.values(),
371 0..,
372 ) |field_name, field, field_index| {
372373 if (!field.ty.hasRuntimeBits(mod)) continue;
373374 // DW.AT.member
374375 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
......@@ -385,6 +386,7 @@ pub const DeclState = struct {
385386 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
386387 }
387388 },
389 else => unreachable,
388390 }
389391
390392 // DW.AT.structure_type delimit children
src/type.zig+238-568
......@@ -54,10 +54,6 @@ pub const Type = struct {
5454 .error_union => return .ErrorUnion,
5555
5656 .anyframe_T => return .AnyFrame,
57
58 .tuple,
59 .anon_struct,
60 => return .Struct,
6157 },
6258 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
6359 .int_type => return .Int,
......@@ -66,7 +62,7 @@ pub const Type = struct {
6662 .vector_type => return .Vector,
6763 .opt_type => return .Optional,
6864 .error_union_type => return .ErrorUnion,
69 .struct_type => return .Struct,
65 .struct_type, .anon_struct_type => return .Struct,
7066 .union_type => return .Union,
7167 .opaque_type => return .Opaque,
7268 .enum_type => return .Enum,
......@@ -465,76 +461,6 @@ pub const Type = struct {
465461 if (b.zigTypeTag(mod) != .AnyFrame) return false;
466462 return a.elemType2(mod).eql(b.elemType2(mod), mod);
467463 },
468
469 .tuple => {
470 if (!b.isSimpleTuple()) return false;
471
472 const a_tuple = a.tupleFields();
473 const b_tuple = b.tupleFields();
474
475 if (a_tuple.types.len != b_tuple.types.len) return false;
476
477 for (a_tuple.types, 0..) |a_ty, i| {
478 const b_ty = b_tuple.types[i];
479 if (!eql(a_ty, b_ty, mod)) return false;
480 }
481
482 for (a_tuple.values, 0..) |a_val, i| {
483 const ty = a_tuple.types[i];
484 const b_val = b_tuple.values[i];
485 if (a_val.ip_index == .unreachable_value) {
486 if (b_val.ip_index == .unreachable_value) {
487 continue;
488 } else {
489 return false;
490 }
491 } else {
492 if (b_val.ip_index == .unreachable_value) {
493 return false;
494 } else {
495 if (!Value.eql(a_val, b_val, ty, mod)) return false;
496 }
497 }
498 }
499
500 return true;
501 },
502 .anon_struct => {
503 const a_struct_obj = a.castTag(.anon_struct).?.data;
504 const b_struct_obj = (b.castTag(.anon_struct) orelse return false).data;
505
506 if (a_struct_obj.types.len != b_struct_obj.types.len) return false;
507
508 for (a_struct_obj.names, 0..) |a_name, i| {
509 const b_name = b_struct_obj.names[i];
510 if (!std.mem.eql(u8, a_name, b_name)) return false;
511 }
512
513 for (a_struct_obj.types, 0..) |a_ty, i| {
514 const b_ty = b_struct_obj.types[i];
515 if (!eql(a_ty, b_ty, mod)) return false;
516 }
517
518 for (a_struct_obj.values, 0..) |a_val, i| {
519 const ty = a_struct_obj.types[i];
520 const b_val = b_struct_obj.values[i];
521 if (a_val.ip_index == .unreachable_value) {
522 if (b_val.ip_index == .unreachable_value) {
523 continue;
524 } else {
525 return false;
526 }
527 } else {
528 if (b_val.ip_index == .unreachable_value) {
529 return false;
530 } else {
531 if (!Value.eql(a_val, b_val, ty, mod)) return false;
532 }
533 }
534 }
535
536 return true;
537 },
538464 }
539465 }
540466
......@@ -641,34 +567,6 @@ pub const Type = struct {
641567 std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame);
642568 hashWithHasher(ty.childType(mod), hasher, mod);
643569 },
644
645 .tuple => {
646 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
647
648 const tuple = ty.tupleFields();
649 std.hash.autoHash(hasher, tuple.types.len);
650
651 for (tuple.types, 0..) |field_ty, i| {
652 hashWithHasher(field_ty, hasher, mod);
653 const field_val = tuple.values[i];
654 if (field_val.ip_index == .unreachable_value) continue;
655 field_val.hash(field_ty, hasher, mod);
656 }
657 },
658 .anon_struct => {
659 const struct_obj = ty.castTag(.anon_struct).?.data;
660 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
661 std.hash.autoHash(hasher, struct_obj.types.len);
662
663 for (struct_obj.types, 0..) |field_ty, i| {
664 const field_name = struct_obj.names[i];
665 const field_val = struct_obj.values[i];
666 hasher.update(field_name);
667 hashWithHasher(field_ty, hasher, mod);
668 if (field_val.ip_index == .unreachable_value) continue;
669 field_val.hash(field_ty, hasher, mod);
670 }
671 },
672570 }
673571 }
674572
......@@ -733,41 +631,6 @@ pub const Type = struct {
733631 };
734632 },
735633
736 .tuple => {
737 const payload = self.castTag(.tuple).?.data;
738 const types = try allocator.alloc(Type, payload.types.len);
739 const values = try allocator.alloc(Value, payload.values.len);
740 for (payload.types, 0..) |ty, i| {
741 types[i] = try ty.copy(allocator);
742 }
743 for (payload.values, 0..) |val, i| {
744 values[i] = try val.copy(allocator);
745 }
746 return Tag.tuple.create(allocator, .{
747 .types = types,
748 .values = values,
749 });
750 },
751 .anon_struct => {
752 const payload = self.castTag(.anon_struct).?.data;
753 const names = try allocator.alloc([]const u8, payload.names.len);
754 const types = try allocator.alloc(Type, payload.types.len);
755 const values = try allocator.alloc(Value, payload.values.len);
756 for (payload.names, 0..) |name, i| {
757 names[i] = try allocator.dupe(u8, name);
758 }
759 for (payload.types, 0..) |ty, i| {
760 types[i] = try ty.copy(allocator);
761 }
762 for (payload.values, 0..) |val, i| {
763 values[i] = try val.copy(allocator);
764 }
765 return Tag.anon_struct.create(allocator, .{
766 .names = names,
767 .types = types,
768 .values = values,
769 });
770 },
771634 .function => {
772635 const payload = self.castTag(.function).?.data;
773636 const param_types = try allocator.alloc(Type, payload.param_types.len);
......@@ -935,42 +798,6 @@ pub const Type = struct {
935798 ty = return_type;
936799 continue;
937800 },
938 .tuple => {
939 const tuple = ty.castTag(.tuple).?.data;
940 try writer.writeAll("tuple{");
941 for (tuple.types, 0..) |field_ty, i| {
942 if (i != 0) try writer.writeAll(", ");
943 const val = tuple.values[i];
944 if (val.ip_index != .unreachable_value) {
945 try writer.writeAll("comptime ");
946 }
947 try field_ty.dump("", .{}, writer);
948 if (val.ip_index != .unreachable_value) {
949 try writer.print(" = {}", .{val.fmtDebug()});
950 }
951 }
952 try writer.writeAll("}");
953 return;
954 },
955 .anon_struct => {
956 const anon_struct = ty.castTag(.anon_struct).?.data;
957 try writer.writeAll("struct{");
958 for (anon_struct.types, 0..) |field_ty, i| {
959 if (i != 0) try writer.writeAll(", ");
960 const val = anon_struct.values[i];
961 if (val.ip_index != .unreachable_value) {
962 try writer.writeAll("comptime ");
963 }
964 try writer.writeAll(anon_struct.names[i]);
965 try writer.writeAll(": ");
966 try field_ty.dump("", .{}, writer);
967 if (val.ip_index != .unreachable_value) {
968 try writer.print(" = {}", .{val.fmtDebug()});
969 }
970 }
971 try writer.writeAll("}");
972 return;
973 },
974801 .optional => {
975802 const child_type = ty.castTag(.optional).?.data;
976803 try writer.writeByte('?');
......@@ -1131,45 +958,6 @@ pub const Type = struct {
1131958 try print(error_union.payload, writer, mod);
1132959 },
1133960
1134 .tuple => {
1135 const tuple = ty.castTag(.tuple).?.data;
1136
1137 try writer.writeAll("tuple{");
1138 for (tuple.types, 0..) |field_ty, i| {
1139 if (i != 0) try writer.writeAll(", ");
1140 const val = tuple.values[i];
1141 if (val.ip_index != .unreachable_value) {
1142 try writer.writeAll("comptime ");
1143 }
1144 try print(field_ty, writer, mod);
1145 if (val.ip_index != .unreachable_value) {
1146 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1147 }
1148 }
1149 try writer.writeAll("}");
1150 },
1151 .anon_struct => {
1152 const anon_struct = ty.castTag(.anon_struct).?.data;
1153
1154 try writer.writeAll("struct{");
1155 for (anon_struct.types, 0..) |field_ty, i| {
1156 if (i != 0) try writer.writeAll(", ");
1157 const val = anon_struct.values[i];
1158 if (val.ip_index != .unreachable_value) {
1159 try writer.writeAll("comptime ");
1160 }
1161 try writer.writeAll(anon_struct.names[i]);
1162 try writer.writeAll(": ");
1163
1164 try print(field_ty, writer, mod);
1165
1166 if (val.ip_index != .unreachable_value) {
1167 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1168 }
1169 }
1170 try writer.writeAll("}");
1171 },
1172
1173961 .pointer => {
1174962 const info = ty.ptrInfo(mod);
1175963
......@@ -1335,6 +1123,27 @@ pub const Type = struct {
13351123 try writer.writeAll("@TypeOf(.{})");
13361124 }
13371125 },
1126 .anon_struct_type => |anon_struct| {
1127 try writer.writeAll("struct{");
1128 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {
1129 if (i != 0) try writer.writeAll(", ");
1130 if (val != .none) {
1131 try writer.writeAll("comptime ");
1132 }
1133 if (anon_struct.names.len != 0) {
1134 const name = mod.intern_pool.stringToSlice(anon_struct.names[i]);
1135 try writer.writeAll(name);
1136 try writer.writeAll(": ");
1137 }
1138
1139 try print(field_ty.toType(), writer, mod);
1140
1141 if (val != .none) {
1142 try writer.print(" = {}", .{val.toValue().fmtValue(field_ty.toType(), mod)});
1143 }
1144 }
1145 try writer.writeAll("}");
1146 },
13381147
13391148 .union_type => |union_type| {
13401149 const union_obj = mod.unionPtr(union_type.index);
......@@ -1443,16 +1252,6 @@ pub const Type = struct {
14431252 }
14441253 },
14451254
1446 .tuple, .anon_struct => {
1447 const tuple = ty.tupleFields();
1448 for (tuple.types, 0..) |field_ty, i| {
1449 const val = tuple.values[i];
1450 if (val.ip_index != .unreachable_value) continue; // comptime field
1451 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
1452 }
1453 return false;
1454 },
1455
14561255 .inferred_alloc_const => unreachable,
14571256 .inferred_alloc_mut => unreachable,
14581257 },
......@@ -1567,6 +1366,13 @@ pub const Type = struct {
15671366 return false;
15681367 }
15691368 },
1369 .anon_struct_type => |tuple| {
1370 for (tuple.types, tuple.values) |field_ty, val| {
1371 if (val != .none) continue; // comptime field
1372 if (try field_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
1373 }
1374 return false;
1375 },
15701376
15711377 .union_type => |union_type| {
15721378 const union_obj = mod.unionPtr(union_type.index);
......@@ -1634,8 +1440,6 @@ pub const Type = struct {
16341440 .function,
16351441 .error_union,
16361442 .anyframe_T,
1637 .tuple,
1638 .anon_struct,
16391443 => false,
16401444
16411445 .inferred_alloc_mut => unreachable,
......@@ -1705,6 +1509,7 @@ pub const Type = struct {
17051509 };
17061510 return struct_obj.layout != .Auto;
17071511 },
1512 .anon_struct_type => false,
17081513 .union_type => |union_type| switch (union_type.runtime_tag) {
17091514 .none, .safety => mod.unionPtr(union_type.index).layout != .Auto,
17101515 .tagged => false,
......@@ -1923,26 +1728,6 @@ pub const Type = struct {
19231728 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
19241729 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
19251730
1926 .tuple, .anon_struct => {
1927 const tuple = ty.tupleFields();
1928 var big_align: u32 = 0;
1929 for (tuple.types, 0..) |field_ty, i| {
1930 const val = tuple.values[i];
1931 if (val.ip_index != .unreachable_value) continue; // comptime field
1932 if (!(field_ty.hasRuntimeBits(mod))) continue;
1933
1934 switch (try field_ty.abiAlignmentAdvanced(mod, strat)) {
1935 .scalar => |field_align| big_align = @max(big_align, field_align),
1936 .val => switch (strat) {
1937 .eager => unreachable, // field type alignment not resolved
1938 .sema => unreachable, // passed to abiAlignmentAdvanced above
1939 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1940 },
1941 }
1942 }
1943 return AbiAlignmentAdvanced{ .scalar = big_align };
1944 },
1945
19461731 .inferred_alloc_const,
19471732 .inferred_alloc_mut,
19481733 => unreachable,
......@@ -2100,6 +1885,24 @@ pub const Type = struct {
21001885 }
21011886 return AbiAlignmentAdvanced{ .scalar = big_align };
21021887 },
1888 .anon_struct_type => |tuple| {
1889 var big_align: u32 = 0;
1890 for (tuple.types, tuple.values) |field_ty, val| {
1891 if (val != .none) continue; // comptime field
1892 if (!(field_ty.toType().hasRuntimeBits(mod))) continue;
1893
1894 switch (try field_ty.toType().abiAlignmentAdvanced(mod, strat)) {
1895 .scalar => |field_align| big_align = @max(big_align, field_align),
1896 .val => switch (strat) {
1897 .eager => unreachable, // field type alignment not resolved
1898 .sema => unreachable, // passed to abiAlignmentAdvanced above
1899 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1900 },
1901 }
1902 }
1903 return AbiAlignmentAdvanced{ .scalar = big_align };
1904 },
1905
21031906 .union_type => |union_type| {
21041907 const union_obj = mod.unionPtr(union_type.index);
21051908 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
......@@ -2287,18 +2090,6 @@ pub const Type = struct {
22872090 .inferred_alloc_const => unreachable,
22882091 .inferred_alloc_mut => unreachable,
22892092
2290 .tuple, .anon_struct => {
2291 switch (strat) {
2292 .sema => |sema| try sema.resolveTypeLayout(ty),
2293 .lazy, .eager => {},
2294 }
2295 const field_count = ty.structFieldCount(mod);
2296 if (field_count == 0) {
2297 return AbiSizeAdvanced{ .scalar = 0 };
2298 }
2299 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
2300 },
2301
23022093 .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
23032094
23042095 .pointer => switch (ty.castTag(.pointer).?.data.size) {
......@@ -2496,6 +2287,18 @@ pub const Type = struct {
24962287 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
24972288 },
24982289 },
2290 .anon_struct_type => |tuple| {
2291 switch (strat) {
2292 .sema => |sema| try sema.resolveTypeLayout(ty),
2293 .lazy, .eager => {},
2294 }
2295 const field_count = tuple.types.len;
2296 if (field_count == 0) {
2297 return AbiSizeAdvanced{ .scalar = 0 };
2298 }
2299 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
2300 },
2301
24992302 .union_type => |union_type| {
25002303 const union_obj = mod.unionPtr(union_type.index);
25012304 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
......@@ -2609,18 +2412,6 @@ pub const Type = struct {
26092412 .inferred_alloc_const => unreachable,
26102413 .inferred_alloc_mut => unreachable,
26112414
2612 .tuple, .anon_struct => {
2613 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2614 if (ty.containerLayout(mod) != .Packed) {
2615 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2616 }
2617 var total: u64 = 0;
2618 for (ty.tupleFields().types) |field_ty| {
2619 total += try bitSizeAdvanced(field_ty, mod, opt_sema);
2620 }
2621 return total;
2622 },
2623
26242415 .anyframe_T => return target.ptrBitWidth(),
26252416
26262417 .pointer => switch (ty.castTag(.pointer).?.data.size) {
......@@ -2724,6 +2515,11 @@ pub const Type = struct {
27242515 return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema);
27252516 },
27262517
2518 .anon_struct_type => {
2519 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
2520 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
2521 },
2522
27272523 .union_type => |union_type| {
27282524 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
27292525 if (ty.containerLayout(mod) != .Packed) {
......@@ -3220,23 +3016,17 @@ pub const Type = struct {
32203016 }
32213017
32223018 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
3223 return switch (ty.ip_index) {
3224 .empty_struct_type => .Auto,
3225 .none => switch (ty.tag()) {
3226 .tuple, .anon_struct => .Auto,
3227 else => unreachable,
3019 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3020 .struct_type => |struct_type| {
3021 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto;
3022 return struct_obj.layout;
32283023 },
3229 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3230 .struct_type => |struct_type| {
3231 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto;
3232 return struct_obj.layout;
3233 },
3234 .union_type => |union_type| {
3235 const union_obj = mod.unionPtr(union_type.index);
3236 return union_obj.layout;
3237 },
3238 else => unreachable,
3024 .anon_struct_type => .Auto,
3025 .union_type => |union_type| {
3026 const union_obj = mod.unionPtr(union_type.index);
3027 return union_obj.layout;
32393028 },
3029 else => unreachable,
32403030 };
32413031 }
32423032
......@@ -3349,23 +3139,16 @@ pub const Type = struct {
33493139 }
33503140
33513141 pub fn arrayLenIp(ty: Type, ip: InternPool) u64 {
3352 return switch (ty.ip_index) {
3353 .empty_struct_type => 0,
3354 .none => switch (ty.tag()) {
3355 .tuple => ty.castTag(.tuple).?.data.types.len,
3356 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
3357
3358 else => unreachable,
3359 },
3360 else => switch (ip.indexToKey(ty.ip_index)) {
3361 .vector_type => |vector_type| vector_type.len,
3362 .array_type => |array_type| array_type.len,
3363 .struct_type => |struct_type| {
3364 const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0;
3365 return struct_obj.fields.count();
3366 },
3367 else => unreachable,
3142 return switch (ip.indexToKey(ty.ip_index)) {
3143 .vector_type => |vector_type| vector_type.len,
3144 .array_type => |array_type| array_type.len,
3145 .struct_type => |struct_type| {
3146 const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0;
3147 return struct_obj.fields.count();
33683148 },
3149 .anon_struct_type => |tuple| tuple.types.len,
3150
3151 else => unreachable,
33693152 };
33703153 }
33713154
......@@ -3374,16 +3157,10 @@ pub const Type = struct {
33743157 }
33753158
33763159 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
3377 return switch (ty.ip_index) {
3378 .none => switch (ty.tag()) {
3379 .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),
3380 .anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len),
3381 else => unreachable,
3382 },
3383 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3384 .vector_type => |vector_type| vector_type.len,
3385 else => unreachable,
3386 },
3160 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3161 .vector_type => |vector_type| vector_type.len,
3162 .anon_struct_type => |tuple| @intCast(u32, tuple.types.len),
3163 else => unreachable,
33873164 };
33883165 }
33893166
......@@ -3391,8 +3168,6 @@ pub const Type = struct {
33913168 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
33923169 return switch (ty.ip_index) {
33933170 .none => switch (ty.tag()) {
3394 .tuple => null,
3395
33963171 .pointer => ty.castTag(.pointer).?.data.sentinel,
33973172
33983173 else => unreachable,
......@@ -3400,6 +3175,7 @@ pub const Type = struct {
34003175 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
34013176 .vector_type,
34023177 .struct_type,
3178 .anon_struct_type,
34033179 => null,
34043180
34053181 .array_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null,
......@@ -3486,10 +3262,12 @@ pub const Type = struct {
34863262 ty = struct_obj.backing_int_ty;
34873263 },
34883264 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),
3265 .vector_type => |vector_type| ty = vector_type.child.toType(),
3266
3267 .anon_struct_type => unreachable,
34893268
34903269 .ptr_type => unreachable,
34913270 .array_type => unreachable,
3492 .vector_type => |vector_type| ty = vector_type.child.toType(),
34933271
34943272 .opt_type => unreachable,
34953273 .error_union_type => unreachable,
......@@ -3711,17 +3489,6 @@ pub const Type = struct {
37113489 }
37123490 },
37133491
3714 .tuple, .anon_struct => {
3715 const tuple = ty.tupleFields();
3716 for (tuple.values, 0..) |val, i| {
3717 const is_comptime = val.ip_index != .unreachable_value;
3718 if (is_comptime) continue;
3719 if ((try tuple.types[i].onePossibleValue(mod)) != null) continue;
3720 return null;
3721 }
3722 return Value.empty_struct;
3723 },
3724
37253492 .inferred_alloc_const => unreachable,
37263493 .inferred_alloc_mut => unreachable,
37273494 },
......@@ -3810,7 +3577,33 @@ pub const Type = struct {
38103577 return null;
38113578 }
38123579 }
3813 // In this case the struct has no fields and therefore has one possible value.
3580 // In this case the struct has no runtime-known fields and
3581 // therefore has one possible value.
3582
3583 // TODO: this is incorrect for structs with comptime fields, I think
3584 // we should use a temporary allocator to construct an aggregate that
3585 // is populated with the comptime values and then intern that value here.
3586 // This TODO is repeated for anon_struct_type below, as well as in
3587 // the redundant implementation of one-possible-value logic in Sema.zig.
3588 const empty = try mod.intern(.{ .aggregate = .{
3589 .ty = ty.ip_index,
3590 .fields = &.{},
3591 } });
3592 return empty.toValue();
3593 },
3594
3595 .anon_struct_type => |tuple| {
3596 for (tuple.types, tuple.values) |field_ty, val| {
3597 if (val != .none) continue; // comptime field
3598 if ((try field_ty.toType().onePossibleValue(mod)) != null) continue;
3599 return null;
3600 }
3601
3602 // TODO: this is incorrect for structs with comptime fields, I think
3603 // we should use a temporary allocator to construct an aggregate that
3604 // is populated with the comptime values and then intern that value here.
3605 // This TODO is repeated for struct_type above, as well as in
3606 // the redundant implementation of one-possible-value logic in Sema.zig.
38143607 const empty = try mod.intern(.{ .aggregate = .{
38153608 .ty = ty.ip_index,
38163609 .fields = &.{},
......@@ -3915,15 +3708,6 @@ pub const Type = struct {
39153708 return ty.optionalChild(mod).comptimeOnly(mod);
39163709 },
39173710
3918 .tuple, .anon_struct => {
3919 const tuple = ty.tupleFields();
3920 for (tuple.types, 0..) |field_ty, i| {
3921 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
3922 if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true;
3923 }
3924 return false;
3925 },
3926
39273711 .error_union => return ty.errorUnionPayload().comptimeOnly(mod),
39283712 .anyframe_T => {
39293713 const child_ty = ty.castTag(.anyframe_T).?.data;
......@@ -4007,6 +3791,14 @@ pub const Type = struct {
40073791 }
40083792 },
40093793
3794 .anon_struct_type => |tuple| {
3795 for (tuple.types, tuple.values) |field_ty, val| {
3796 const have_comptime_val = val != .none;
3797 if (!have_comptime_val and field_ty.toType().comptimeOnly(mod)) return true;
3798 }
3799 return false;
3800 },
3801
40103802 .union_type => |union_type| {
40113803 const union_obj = mod.unionPtr(union_type.index);
40123804 switch (union_obj.requires_comptime) {
......@@ -4275,171 +4067,116 @@ pub const Type = struct {
42754067 }
42764068
42774069 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) []const u8 {
4278 switch (ty.ip_index) {
4279 .none => switch (ty.tag()) {
4280 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],
4281 else => unreachable,
4070 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4071 .struct_type => |struct_type| {
4072 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4073 assert(struct_obj.haveFieldTypes());
4074 return struct_obj.fields.keys()[field_index];
42824075 },
4283 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4284 .struct_type => |struct_type| {
4285 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4286 assert(struct_obj.haveFieldTypes());
4287 return struct_obj.fields.keys()[field_index];
4288 },
4289 else => unreachable,
4076 .anon_struct_type => |anon_struct| {
4077 const name = anon_struct.names[field_index];
4078 return mod.intern_pool.stringToSlice(name);
42904079 },
4080 else => unreachable,
42914081 }
42924082 }
42934083
42944084 pub fn structFieldCount(ty: Type, mod: *Module) usize {
4295 return switch (ty.ip_index) {
4296 .empty_struct_type => 0,
4297 .none => switch (ty.tag()) {
4298 .tuple => ty.castTag(.tuple).?.data.types.len,
4299 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
4300 else => unreachable,
4301 },
4302 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4303 .struct_type => |struct_type| {
4304 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
4305 assert(struct_obj.haveFieldTypes());
4306 return struct_obj.fields.count();
4307 },
4308 else => unreachable,
4085 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4086 .struct_type => |struct_type| {
4087 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
4088 assert(struct_obj.haveFieldTypes());
4089 return struct_obj.fields.count();
43094090 },
4091 .anon_struct_type => |anon_struct| anon_struct.types.len,
4092 else => unreachable,
43104093 };
43114094 }
43124095
43134096 /// Supports structs and unions.
43144097 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
4315 return switch (ty.ip_index) {
4316 .none => switch (ty.tag()) {
4317 .tuple => return ty.castTag(.tuple).?.data.types[index],
4318 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
4319 else => unreachable,
4098 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4099 .struct_type => |struct_type| {
4100 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4101 return struct_obj.fields.values()[index].ty;
43204102 },
4321 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4322 .struct_type => |struct_type| {
4323 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4324 return struct_obj.fields.values()[index].ty;
4325 },
4326 .union_type => |union_type| {
4327 const union_obj = mod.unionPtr(union_type.index);
4328 return union_obj.fields.values()[index].ty;
4329 },
4330 else => unreachable,
4103 .union_type => |union_type| {
4104 const union_obj = mod.unionPtr(union_type.index);
4105 return union_obj.fields.values()[index].ty;
43314106 },
4107 .anon_struct_type => |anon_struct| anon_struct.types[index].toType(),
4108 else => unreachable,
43324109 };
43334110 }
43344111
43354112 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {
4336 switch (ty.ip_index) {
4337 .none => switch (ty.tag()) {
4338 .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod),
4339 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod),
4340 else => unreachable,
4113 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4114 .struct_type => |struct_type| {
4115 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4116 assert(struct_obj.layout != .Packed);
4117 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
43414118 },
4342 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4343 .struct_type => |struct_type| {
4344 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4345 assert(struct_obj.layout != .Packed);
4346 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
4347 },
4348 .union_type => |union_type| {
4349 const union_obj = mod.unionPtr(union_type.index);
4350 return union_obj.fields.values()[index].normalAlignment(mod);
4351 },
4352 else => unreachable,
4119 .anon_struct_type => |anon_struct| {
4120 return anon_struct.types[index].toType().abiAlignment(mod);
43534121 },
4122 .union_type => |union_type| {
4123 const union_obj = mod.unionPtr(union_type.index);
4124 return union_obj.fields.values()[index].normalAlignment(mod);
4125 },
4126 else => unreachable,
43544127 }
43554128 }
43564129
43574130 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
4358 switch (ty.ip_index) {
4359 .none => switch (ty.tag()) {
4360 .tuple => {
4361 const tuple = ty.castTag(.tuple).?.data;
4362 return tuple.values[index];
4363 },
4364 .anon_struct => {
4365 const struct_obj = ty.castTag(.anon_struct).?.data;
4366 return struct_obj.values[index];
4367 },
4368 else => unreachable,
4131 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4132 .struct_type => |struct_type| {
4133 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4134 return struct_obj.fields.values()[index].default_val;
43694135 },
4370 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4371 .struct_type => |struct_type| {
4372 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4373 return struct_obj.fields.values()[index].default_val;
4374 },
4375 else => unreachable,
4136 .anon_struct_type => |anon_struct| {
4137 const val = anon_struct.values[index];
4138 // TODO: avoid using `unreachable` to indicate this.
4139 if (val == .none) return Value.@"unreachable";
4140 return val.toValue();
43764141 },
4142 else => unreachable,
43774143 }
43784144 }
43794145
43804146 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
4381 switch (ty.ip_index) {
4382 .none => switch (ty.tag()) {
4383 .tuple => {
4384 const tuple = ty.castTag(.tuple).?.data;
4385 const val = tuple.values[index];
4386 if (val.ip_index == .unreachable_value) {
4387 return tuple.types[index].onePossibleValue(mod);
4388 } else {
4389 return val;
4390 }
4391 },
4392 .anon_struct => {
4393 const anon_struct = ty.castTag(.anon_struct).?.data;
4394 const val = anon_struct.values[index];
4395 if (val.ip_index == .unreachable_value) {
4396 return anon_struct.types[index].onePossibleValue(mod);
4397 } else {
4398 return val;
4399 }
4400 },
4401 else => unreachable,
4147 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4148 .struct_type => |struct_type| {
4149 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4150 const field = struct_obj.fields.values()[index];
4151 if (field.is_comptime) {
4152 return field.default_val;
4153 } else {
4154 return field.ty.onePossibleValue(mod);
4155 }
44024156 },
4403 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4404 .struct_type => |struct_type| {
4405 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4406 const field = struct_obj.fields.values()[index];
4407 if (field.is_comptime) {
4408 return field.default_val;
4409 } else {
4410 return field.ty.onePossibleValue(mod);
4411 }
4412 },
4413 else => unreachable,
4157 .anon_struct_type => |tuple| {
4158 const val = tuple.values[index];
4159 if (val == .none) {
4160 return tuple.types[index].toType().onePossibleValue(mod);
4161 } else {
4162 return val.toValue();
4163 }
44144164 },
4165 else => unreachable,
44154166 }
44164167 }
44174168
44184169 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
4419 switch (ty.ip_index) {
4420 .none => switch (ty.tag()) {
4421 .tuple => {
4422 const tuple = ty.castTag(.tuple).?.data;
4423 const val = tuple.values[index];
4424 return val.ip_index != .unreachable_value;
4425 },
4426 .anon_struct => {
4427 const anon_struct = ty.castTag(.anon_struct).?.data;
4428 const val = anon_struct.values[index];
4429 return val.ip_index != .unreachable_value;
4430 },
4431 else => unreachable,
4432 },
4433 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4434 .struct_type => |struct_type| {
4435 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4436 if (struct_obj.layout == .Packed) return false;
4437 const field = struct_obj.fields.values()[index];
4438 return field.is_comptime;
4439 },
4440 else => unreachable,
4170 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4171 .struct_type => |struct_type| {
4172 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4173 if (struct_obj.layout == .Packed) return false;
4174 const field = struct_obj.fields.values()[index];
4175 return field.is_comptime;
44414176 },
4442 }
4177 .anon_struct_type => |anon_struct| anon_struct.values[index] != .none,
4178 else => unreachable,
4179 };
44434180 }
44444181
44454182 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
......@@ -4516,46 +4253,43 @@ pub const Type = struct {
45164253 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
45174254 switch (ty.ip_index) {
45184255 .none => switch (ty.tag()) {
4519 .tuple, .anon_struct => {
4520 const tuple = ty.tupleFields();
4256 else => unreachable,
4257 },
4258 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4259 .struct_type => |struct_type| {
4260 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4261 assert(struct_obj.haveLayout());
4262 assert(struct_obj.layout != .Packed);
4263 var it = ty.iterateStructOffsets(mod);
4264 while (it.next()) |field_offset| {
4265 if (index == field_offset.field)
4266 return field_offset.offset;
4267 }
45214268
4269 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
4270 },
4271
4272 .anon_struct_type => |tuple| {
45224273 var offset: u64 = 0;
45234274 var big_align: u32 = 0;
45244275
4525 for (tuple.types, 0..) |field_ty, i| {
4526 const field_val = tuple.values[i];
4527 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) {
4276 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
4277 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {
45284278 // comptime field
45294279 if (i == index) return offset;
45304280 continue;
45314281 }
45324282
4533 const field_align = field_ty.abiAlignment(mod);
4283 const field_align = field_ty.toType().abiAlignment(mod);
45344284 big_align = @max(big_align, field_align);
45354285 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
45364286 if (i == index) return offset;
4537 offset += field_ty.abiSize(mod);
4287 offset += field_ty.toType().abiSize(mod);
45384288 }
45394289 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
45404290 return offset;
45414291 },
45424292
4543 else => unreachable,
4544 },
4545 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4546 .struct_type => |struct_type| {
4547 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
4548 assert(struct_obj.haveLayout());
4549 assert(struct_obj.layout != .Packed);
4550 var it = ty.iterateStructOffsets(mod);
4551 while (it.next()) |field_offset| {
4552 if (index == field_offset.field)
4553 return field_offset.offset;
4554 }
4555
4556 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
4557 },
4558
45594293 .union_type => |union_type| {
45604294 if (!union_type.hasTag())
45614295 return 0;
......@@ -4655,10 +4389,6 @@ pub const Type = struct {
46554389 inferred_alloc_const, // See last_no_payload_tag below.
46564390 // After this, the tag requires a payload.
46574391
4658 /// Possible Value tags for this: @"struct"
4659 tuple,
4660 /// Possible Value tags for this: @"struct"
4661 anon_struct,
46624392 pointer,
46634393 function,
46644394 optional,
......@@ -4691,8 +4421,6 @@ pub const Type = struct {
46914421 .function => Payload.Function,
46924422 .error_union => Payload.ErrorUnion,
46934423 .error_set_single => Payload.Name,
4694 .tuple => Payload.Tuple,
4695 .anon_struct => Payload.AnonStruct,
46964424 };
46974425 }
46984426
......@@ -4723,83 +4451,48 @@ pub const Type = struct {
47234451
47244452 pub fn isTuple(ty: Type, mod: *Module) bool {
47254453 return switch (ty.ip_index) {
4726 .none => switch (ty.tag()) {
4727 .tuple => true,
4728 else => false,
4729 },
4730 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4454 .none => false,
4455 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
47314456 .struct_type => |struct_type| {
47324457 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
47334458 return struct_obj.is_tuple;
47344459 },
4460 .anon_struct_type => |anon_struct| anon_struct.names.len == 0,
47354461 else => false,
47364462 },
47374463 };
47384464 }
47394465
4740 pub fn isAnonStruct(ty: Type) bool {
4741 return switch (ty.ip_index) {
4742 .empty_struct_type => true,
4743 .none => switch (ty.tag()) {
4744 .anon_struct => true,
4745 else => false,
4746 },
4466 pub fn isAnonStruct(ty: Type, mod: *Module) bool {
4467 if (ty.ip_index == .empty_struct_type) return true;
4468 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4469 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len > 0,
47474470 else => false,
47484471 };
47494472 }
47504473
47514474 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
4752 return switch (ty.ip_index) {
4753 .empty_struct_type => true,
4754 .none => switch (ty.tag()) {
4755 .tuple, .anon_struct => true,
4756 else => false,
4757 },
4758 else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4759 .struct_type => |struct_type| {
4760 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
4761 return struct_obj.is_tuple;
4762 },
4763 else => false,
4764 },
4765 };
4766 }
4767
4768 pub fn isSimpleTuple(ty: Type) bool {
4769 return switch (ty.ip_index) {
4770 .empty_struct_type => true,
4771 .none => switch (ty.tag()) {
4772 .tuple => true,
4773 else => false,
4475 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4476 .struct_type => |struct_type| {
4477 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
4478 return struct_obj.is_tuple;
47744479 },
4480 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
47754481 else => false,
47764482 };
47774483 }
47784484
4779 pub fn isSimpleTupleOrAnonStruct(ty: Type) bool {
4780 return switch (ty.ip_index) {
4781 .empty_struct_type => true,
4782 .none => switch (ty.tag()) {
4783 .tuple, .anon_struct => true,
4784 else => false,
4785 },
4485 pub fn isSimpleTuple(ty: Type, mod: *Module) bool {
4486 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4487 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
47864488 else => false,
47874489 };
47884490 }
47894491
4790 // Only allowed for simple tuple types
4791 pub fn tupleFields(ty: Type) Payload.Tuple.Data {
4792 return switch (ty.ip_index) {
4793 .empty_struct_type => .{ .types = &.{}, .values = &.{} },
4794 .none => switch (ty.tag()) {
4795 .tuple => ty.castTag(.tuple).?.data,
4796 .anon_struct => .{
4797 .types = ty.castTag(.anon_struct).?.data.types,
4798 .values = ty.castTag(.anon_struct).?.data.values,
4799 },
4800 else => unreachable,
4801 },
4802 else => unreachable,
4492 pub fn isSimpleTupleOrAnonStruct(ty: Type, mod: *Module) bool {
4493 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4494 .anon_struct_type => true,
4495 else => false,
48034496 };
48044497 }
48054498
......@@ -4947,29 +4640,6 @@ pub const Type = struct {
49474640 /// memory is owned by `Module`
49484641 data: []const u8,
49494642 };
4950
4951 pub const Tuple = struct {
4952 base: Payload = .{ .tag = .tuple },
4953 data: Data,
4954
4955 pub const Data = struct {
4956 types: []Type,
4957 /// unreachable_value elements are used to indicate runtime-known.
4958 values: []Value,
4959 };
4960 };
4961
4962 pub const AnonStruct = struct {
4963 base: Payload = .{ .tag = .anon_struct },
4964 data: Data,
4965
4966 pub const Data = struct {
4967 names: []const []const u8,
4968 types: []Type,
4969 /// unreachable_value elements are used to indicate runtime-known.
4970 values: []Value,
4971 };
4972 };
49734643 };
49744644
49754645 pub const @"u1": Type = .{ .ip_index = .u1_type, .legacy = undefined };
src/value.zig+20-32
......@@ -1889,26 +1889,28 @@ pub const Value = struct {
18891889 const b_field_vals = b.castTag(.aggregate).?.data;
18901890 assert(a_field_vals.len == b_field_vals.len);
18911891
1892 if (ty.isSimpleTupleOrAnonStruct()) {
1893 const types = ty.tupleFields().types;
1894 assert(types.len == a_field_vals.len);
1895 for (types, 0..) |field_ty, i| {
1896 if (!(try eqlAdvanced(a_field_vals[i], field_ty, b_field_vals[i], field_ty, mod, opt_sema))) {
1897 return false;
1892 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1893 .anon_struct_type => |anon_struct| {
1894 assert(anon_struct.types.len == a_field_vals.len);
1895 for (anon_struct.types, 0..) |field_ty, i| {
1896 if (!(try eqlAdvanced(a_field_vals[i], field_ty.toType(), b_field_vals[i], field_ty.toType(), mod, opt_sema))) {
1897 return false;
1898 }
18981899 }
1899 }
1900 return true;
1901 }
1902
1903 if (ty.zigTypeTag(mod) == .Struct) {
1904 const fields = ty.structFields(mod).values();
1905 assert(fields.len == a_field_vals.len);
1906 for (fields, 0..) |field, i| {
1907 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {
1908 return false;
1900 return true;
1901 },
1902 .struct_type => |struct_type| {
1903 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1904 const fields = struct_obj.fields.values();
1905 assert(fields.len == a_field_vals.len);
1906 for (fields, 0..) |field, i| {
1907 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {
1908 return false;
1909 }
19091910 }
1910 }
1911 return true;
1911 return true;
1912 },
1913 else => {},
19121914 }
19131915
19141916 const elem_ty = ty.childType(mod);
......@@ -2017,20 +2019,6 @@ pub const Value = struct {
20172019 if ((try ty.onePossibleValue(mod)) != null) {
20182020 return true;
20192021 }
2020 if (a_ty.castTag(.anon_struct)) |payload| {
2021 const tuple = payload.data;
2022 if (tuple.values.len != 1) {
2023 return false;
2024 }
2025 const field_name = tuple.names[0];
2026 const union_obj = mod.typeToUnion(ty).?;
2027 const field_index = @intCast(u32, union_obj.fields.getIndex(field_name) orelse return false);
2028 const tag_and_val = b.castTag(.@"union").?.data;
2029 const field_tag = try mod.enumValueFieldIndex(union_obj.tag_ty, field_index);
2030 const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, mod);
2031 if (!tag_matches) return false;
2032 return eqlAdvanced(tag_and_val.val, union_obj.tag_ty, tuple.values[0], tuple.types[0], mod, opt_sema);
2033 }
20342022 return false;
20352023 },
20362024 .Float => {