| author | |
| committer | |
| log | 3ba099bfba9d3c38fe188010aa82fc589b1cabf6 |
| tree | ef96b24aa9e6417e4cfa8c421c0a77ef9b75e22c |
| parent | 8297f28546b44afe49bec074733f05e03a3c0e62 |
18 files changed, 688 insertions(+), 546 deletions(-)
src/InternPool.zig+148-25| ... | ... | @@ -21,6 +21,13 @@ allocated_structs: std.SegmentedList(Module.Struct, 0) = .{}, |
| 21 | 21 | /// When a Struct object is freed from `allocated_structs`, it is pushed into this stack. |
| 22 | 22 | structs_free_list: std.ArrayListUnmanaged(Module.Struct.Index) = .{}, |
| 23 | 23 | |
| 24 | /// Union objects are stored in this data structure because: | |
| 25 | /// * They contain pointers such as the field maps. | |
| 26 | /// * They need to be mutated after creation. | |
| 27 | allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, | |
| 28 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. | |
| 29 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, | |
| 30 | ||
| 24 | 31 | const std = @import("std"); |
| 25 | 32 | const Allocator = std.mem.Allocator; |
| 26 | 33 | const assert = std.debug.assert; |
| ... | ... | @@ -59,10 +66,7 @@ pub const Key = union(enum) { |
| 59 | 66 | /// If `empty_struct_type` is handled separately, then this value may be |
| 60 | 67 | /// safely assumed to never be `none`. |
| 61 | 68 | struct_type: StructType, |
| 62 | union_type: struct { | |
| 63 | fields_len: u32, | |
| 64 | // TODO move Module.Union data to InternPool | |
| 65 | }, | |
| 69 | union_type: UnionType, | |
| 66 | 70 | opaque_type: OpaqueType, |
| 67 | 71 | |
| 68 | 72 | simple_value: SimpleValue, |
| ... | ... | @@ -87,6 +91,8 @@ pub const Key = union(enum) { |
| 87 | 91 | /// In the case of sentinel-terminated arrays, the sentinel value *is* stored, |
| 88 | 92 | /// so the slice length will be one more than the type's array length. |
| 89 | 93 | aggregate: Aggregate, |
| 94 | /// An instance of a union. | |
| 95 | un: Union, | |
| 90 | 96 | |
| 91 | 97 | pub const IntType = std.builtin.Type.Int; |
| 92 | 98 | |
| ... | ... | @@ -145,13 +151,27 @@ pub const Key = union(enum) { |
| 145 | 151 | /// - index == .none |
| 146 | 152 | /// * A struct which has fields as well as a namepace. |
| 147 | 153 | pub const StructType = struct { |
| 148 | /// This will be `none` only in the case of `@TypeOf(.{})` | |
| 149 | /// (`Index.empty_struct_type`). | |
| 150 | namespace: Module.Namespace.OptionalIndex, | |
| 151 | 154 | /// The `none` tag is used to represent two cases: |
| 152 | 155 | /// * `@TypeOf(.{})`, in which case `namespace` will also be `none`. |
| 153 | 156 | /// * A struct with no fields, in which case `namespace` will be populated. |
| 154 | 157 | index: Module.Struct.OptionalIndex, |
| 158 | /// This will be `none` only in the case of `@TypeOf(.{})` | |
| 159 | /// (`Index.empty_struct_type`). | |
| 160 | namespace: Module.Namespace.OptionalIndex, | |
| 161 | }; | |
| 162 | ||
| 163 | pub const UnionType = struct { | |
| 164 | index: Module.Union.Index, | |
| 165 | runtime_tag: RuntimeTag, | |
| 166 | ||
| 167 | pub const RuntimeTag = enum { none, safety, tagged }; | |
| 168 | ||
| 169 | pub fn hasTag(self: UnionType) bool { | |
| 170 | return switch (self.runtime_tag) { | |
| 171 | .none => false, | |
| 172 | .tagged, .safety => true, | |
| 173 | }; | |
| 174 | } | |
| 155 | 175 | }; |
| 156 | 176 | |
| 157 | 177 | pub const Int = struct { |
| ... | ... | @@ -198,6 +218,15 @@ pub const Key = union(enum) { |
| 198 | 218 | val: Index, |
| 199 | 219 | }; |
| 200 | 220 | |
| 221 | pub const Union = struct { | |
| 222 | /// This is the union type; not the field type. | |
| 223 | ty: Index, | |
| 224 | /// Indicates the active field. | |
| 225 | tag: Index, | |
| 226 | /// The value of the active field. | |
| 227 | val: Index, | |
| 228 | }; | |
| 229 | ||
| 201 | 230 | pub const Aggregate = struct { |
| 202 | 231 | ty: Index, |
| 203 | 232 | fields: []const Index, |
| ... | ... | @@ -229,12 +258,10 @@ pub const Key = union(enum) { |
| 229 | 258 | .extern_func, |
| 230 | 259 | .opt, |
| 231 | 260 | .struct_type, |
| 261 | .union_type, | |
| 262 | .un, | |
| 232 | 263 | => |info| std.hash.autoHash(hasher, info), |
| 233 | 264 | |
| 234 | .union_type => |union_type| { | |
| 235 | _ = union_type; | |
| 236 | @panic("TODO"); | |
| 237 | }, | |
| 238 | 265 | .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl), |
| 239 | 266 | |
| 240 | 267 | .int => |int| { |
| ... | ... | @@ -320,6 +347,14 @@ pub const Key = union(enum) { |
| 320 | 347 | const b_info = b.struct_type; |
| 321 | 348 | return std.meta.eql(a_info, b_info); |
| 322 | 349 | }, |
| 350 | .union_type => |a_info| { | |
| 351 | const b_info = b.union_type; | |
| 352 | return std.meta.eql(a_info, b_info); | |
| 353 | }, | |
| 354 | .un => |a_info| { | |
| 355 | const b_info = b.un; | |
| 356 | return std.meta.eql(a_info, b_info); | |
| 357 | }, | |
| 323 | 358 | |
| 324 | 359 | .ptr => |a_info| { |
| 325 | 360 | const b_info = b.ptr; |
| ... | ... | @@ -371,14 +406,6 @@ pub const Key = union(enum) { |
| 371 | 406 | @panic("TODO"); |
| 372 | 407 | }, |
| 373 | 408 | |
| 374 | .union_type => |a_info| { | |
| 375 | const b_info = b.union_type; | |
| 376 | ||
| 377 | _ = a_info; | |
| 378 | _ = b_info; | |
| 379 | @panic("TODO"); | |
| 380 | }, | |
| 381 | ||
| 382 | 409 | .opaque_type => |a_info| { |
| 383 | 410 | const b_info = b.opaque_type; |
| 384 | 411 | return a_info.decl == b_info.decl; |
| ... | ... | @@ -411,6 +438,7 @@ pub const Key = union(enum) { |
| 411 | 438 | .extern_func, |
| 412 | 439 | .enum_tag, |
| 413 | 440 | .aggregate, |
| 441 | .un, | |
| 414 | 442 | => |x| return x.ty, |
| 415 | 443 | |
| 416 | 444 | .simple_value => |s| switch (s) { |
| ... | ... | @@ -838,6 +866,15 @@ pub const Tag = enum(u8) { |
| 838 | 866 | /// Module.Struct object allocated for it. |
| 839 | 867 | /// data is Module.Namespace.Index. |
| 840 | 868 | type_struct_ns, |
| 869 | /// A tagged union type. | |
| 870 | /// `data` is `Module.Union.Index`. | |
| 871 | type_union_tagged, | |
| 872 | /// An untagged union type. It also has no safety tag. | |
| 873 | /// `data` is `Module.Union.Index`. | |
| 874 | type_union_untagged, | |
| 875 | /// An untagged union type which has a safety tag. | |
| 876 | /// `data` is `Module.Union.Index`. | |
| 877 | type_union_safety, | |
| 841 | 878 | |
| 842 | 879 | /// A value that can be represented with only an enum tag. |
| 843 | 880 | /// data is SimpleValue enum value. |
| ... | ... | @@ -908,6 +945,8 @@ pub const Tag = enum(u8) { |
| 908 | 945 | /// * A struct which has 0 fields. |
| 909 | 946 | /// data is Index of the type, which is known to be zero bits at runtime. |
| 910 | 947 | only_possible_value, |
| 948 | /// data is extra index to Key.Union. | |
| 949 | union_value, | |
| 911 | 950 | }; |
| 912 | 951 | |
| 913 | 952 | /// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to |
| ... | ... | @@ -1141,6 +1180,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 1141 | 1180 | ip.structs_free_list.deinit(gpa); |
| 1142 | 1181 | ip.allocated_structs.deinit(gpa); |
| 1143 | 1182 | |
| 1183 | ip.unions_free_list.deinit(gpa); | |
| 1184 | ip.allocated_unions.deinit(gpa); | |
| 1185 | ||
| 1144 | 1186 | ip.* = undefined; |
| 1145 | 1187 | } |
| 1146 | 1188 | |
| ... | ... | @@ -1233,6 +1275,19 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1233 | 1275 | .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(), |
| 1234 | 1276 | } }, |
| 1235 | 1277 | |
| 1278 | .type_union_untagged => .{ .union_type = .{ | |
| 1279 | .index = @intToEnum(Module.Union.Index, data), | |
| 1280 | .runtime_tag = .none, | |
| 1281 | } }, | |
| 1282 | .type_union_tagged => .{ .union_type = .{ | |
| 1283 | .index = @intToEnum(Module.Union.Index, data), | |
| 1284 | .runtime_tag = .tagged, | |
| 1285 | } }, | |
| 1286 | .type_union_safety => .{ .union_type = .{ | |
| 1287 | .index = @intToEnum(Module.Union.Index, data), | |
| 1288 | .runtime_tag = .safety, | |
| 1289 | } }, | |
| 1290 | ||
| 1236 | 1291 | .opt_null => .{ .opt = .{ |
| 1237 | 1292 | .ty = @intToEnum(Index, data), |
| 1238 | 1293 | .val = .none, |
| ... | ... | @@ -1303,6 +1358,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1303 | 1358 | else => unreachable, |
| 1304 | 1359 | }; |
| 1305 | 1360 | }, |
| 1361 | .union_value => .{ .un = ip.extraData(Key.Union, data) }, | |
| 1306 | 1362 | }; |
| 1307 | 1363 | } |
| 1308 | 1364 | |
| ... | ... | @@ -1350,7 +1406,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1350 | 1406 | return @intToEnum(Index, ip.items.len - 1); |
| 1351 | 1407 | } |
| 1352 | 1408 | |
| 1353 | // TODO introduce more pointer encodings | |
| 1354 | 1409 | ip.items.appendAssumeCapacity(.{ |
| 1355 | 1410 | .tag = .type_pointer, |
| 1356 | 1411 | .data = try ip.addExtra(gpa, Pointer{ |
| ... | ... | @@ -1450,8 +1505,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1450 | 1505 | }, |
| 1451 | 1506 | |
| 1452 | 1507 | .union_type => |union_type| { |
| 1453 | _ = union_type; | |
| 1454 | @panic("TODO"); | |
| 1508 | ip.items.appendAssumeCapacity(.{ | |
| 1509 | .tag = switch (union_type.runtime_tag) { | |
| 1510 | .none => .type_union_untagged, | |
| 1511 | .safety => .type_union_safety, | |
| 1512 | .tagged => .type_union_tagged, | |
| 1513 | }, | |
| 1514 | .data = @enumToInt(union_type.index), | |
| 1515 | }); | |
| 1455 | 1516 | }, |
| 1456 | 1517 | |
| 1457 | 1518 | .opaque_type => |opaque_type| { |
| ... | ... | @@ -1642,6 +1703,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1642 | 1703 | } |
| 1643 | 1704 | @panic("TODO"); |
| 1644 | 1705 | }, |
| 1706 | ||
| 1707 | .un => |un| { | |
| 1708 | assert(un.ty != .none); | |
| 1709 | assert(un.tag != .none); | |
| 1710 | assert(un.val != .none); | |
| 1711 | ip.items.appendAssumeCapacity(.{ | |
| 1712 | .tag = .union_value, | |
| 1713 | .data = try ip.addExtra(gpa, un), | |
| 1714 | }); | |
| 1715 | }, | |
| 1645 | 1716 | } |
| 1646 | 1717 | return @intToEnum(Index, ip.items.len - 1); |
| 1647 | 1718 | } |
| ... | ... | @@ -1923,6 +1994,17 @@ pub fn indexToStruct(ip: *InternPool, val: Index) Module.Struct.OptionalIndex { |
| 1923 | 1994 | return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional(); |
| 1924 | 1995 | } |
| 1925 | 1996 | |
| 1997 | pub fn indexToUnion(ip: *InternPool, val: Index) Module.Union.OptionalIndex { | |
| 1998 | const tags = ip.items.items(.tag); | |
| 1999 | if (val == .none) return .none; | |
| 2000 | switch (tags[@enumToInt(val)]) { | |
| 2001 | .type_union_tagged, .type_union_untagged, .type_union_safety => {}, | |
| 2002 | else => return .none, | |
| 2003 | } | |
| 2004 | const datas = ip.items.items(.data); | |
| 2005 | return @intToEnum(Module.Union.Index, datas[@enumToInt(val)]).toOptional(); | |
| 2006 | } | |
| 2007 | ||
| 1926 | 2008 | pub fn isOptionalType(ip: InternPool, ty: Index) bool { |
| 1927 | 2009 | const tags = ip.items.items(.tag); |
| 1928 | 2010 | if (ty == .none) return false; |
| ... | ... | @@ -1937,15 +2019,22 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1937 | 2019 | const items_size = (1 + 4) * ip.items.len; |
| 1938 | 2020 | const extra_size = 4 * ip.extra.items.len; |
| 1939 | 2021 | const limbs_size = 8 * ip.limbs.items.len; |
| 2022 | const structs_size = ip.allocated_structs.len * | |
| 2023 | (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl)); | |
| 2024 | const unions_size = ip.allocated_unions.len * | |
| 2025 | (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl)); | |
| 1940 | 2026 | |
| 1941 | 2027 | // TODO: map overhead size is not taken into account |
| 1942 | const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size; | |
| 2028 | const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size + | |
| 2029 | structs_size + unions_size; | |
| 1943 | 2030 | |
| 1944 | 2031 | std.debug.print( |
| 1945 | 2032 | \\InternPool size: {d} bytes |
| 1946 | 2033 | \\ {d} items: {d} bytes |
| 1947 | 2034 | \\ {d} extra: {d} bytes |
| 1948 | 2035 | \\ {d} limbs: {d} bytes |
| 2036 | \\ {d} structs: {d} bytes | |
| 2037 | \\ {d} unions: {d} bytes | |
| 1949 | 2038 | \\ |
| 1950 | 2039 | , .{ |
| 1951 | 2040 | total_size, |
| ... | ... | @@ -1955,6 +2044,10 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1955 | 2044 | extra_size, |
| 1956 | 2045 | ip.limbs.items.len, |
| 1957 | 2046 | limbs_size, |
| 2047 | ip.allocated_structs.len, | |
| 2048 | structs_size, | |
| 2049 | ip.allocated_unions.len, | |
| 2050 | unions_size, | |
| 1958 | 2051 | }); |
| 1959 | 2052 | |
| 1960 | 2053 | const tags = ip.items.items(.tag); |
| ... | ... | @@ -1980,8 +2073,14 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 1980 | 2073 | .type_error_union => @sizeOf(ErrorUnion), |
| 1981 | 2074 | .type_enum_simple => @sizeOf(EnumSimple), |
| 1982 | 2075 | .type_opaque => @sizeOf(Key.OpaqueType), |
| 1983 | .type_struct => 0, | |
| 1984 | .type_struct_ns => 0, | |
| 2076 | .type_struct => @sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl), | |
| 2077 | .type_struct_ns => @sizeOf(Module.Namespace), | |
| 2078 | ||
| 2079 | .type_union_tagged, | |
| 2080 | .type_union_untagged, | |
| 2081 | .type_union_safety, | |
| 2082 | => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl), | |
| 2083 | ||
| 1985 | 2084 | .simple_type => 0, |
| 1986 | 2085 | .simple_value => 0, |
| 1987 | 2086 | .ptr_int => @sizeOf(PtrInt), |
| ... | ... | @@ -2010,6 +2109,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 2010 | 2109 | .extern_func => @panic("TODO"), |
| 2011 | 2110 | .func => @panic("TODO"), |
| 2012 | 2111 | .only_possible_value => 0, |
| 2112 | .union_value => @sizeOf(Key.Union), | |
| 2013 | 2113 | }); |
| 2014 | 2114 | } |
| 2015 | 2115 | const SortContext = struct { |
| ... | ... | @@ -2041,6 +2141,10 @@ pub fn structPtrUnwrapConst(ip: InternPool, index: Module.Struct.OptionalIndex) |
| 2041 | 2141 | return structPtrConst(ip, index.unwrap() orelse return null); |
| 2042 | 2142 | } |
| 2043 | 2143 | |
| 2144 | pub fn unionPtr(ip: *InternPool, index: Module.Union.Index) *Module.Union { | |
| 2145 | return ip.allocated_unions.at(@enumToInt(index)); | |
| 2146 | } | |
| 2147 | ||
| 2044 | 2148 | pub fn createStruct( |
| 2045 | 2149 | ip: *InternPool, |
| 2046 | 2150 | gpa: Allocator, |
| ... | ... | @@ -2059,3 +2163,22 @@ pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index |
| 2059 | 2163 | // allocation failures here, instead leaking the Struct until garbage collection. |
| 2060 | 2164 | }; |
| 2061 | 2165 | } |
| 2166 | ||
| 2167 | pub fn createUnion( | |
| 2168 | ip: *InternPool, | |
| 2169 | gpa: Allocator, | |
| 2170 | initialization: Module.Union, | |
| 2171 | ) Allocator.Error!Module.Union.Index { | |
| 2172 | if (ip.unions_free_list.popOrNull()) |index| return index; | |
| 2173 | const ptr = try ip.allocated_unions.addOne(gpa); | |
| 2174 | ptr.* = initialization; | |
| 2175 | return @intToEnum(Module.Union.Index, ip.allocated_unions.len - 1); | |
| 2176 | } | |
| 2177 | ||
| 2178 | pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) void { | |
| 2179 | ip.unionPtr(index).* = undefined; | |
| 2180 | ip.unions_free_list.append(gpa, index) catch { | |
| 2181 | // In order to keep `destroyUnion` a non-fallible function, we ignore memory | |
| 2182 | // allocation failures here, instead leaking the Union until garbage collection. | |
| 2183 | }; | |
| 2184 | } |
src/Module.zig+57-20| ... | ... | @@ -851,11 +851,10 @@ pub const Decl = struct { |
| 851 | 851 | |
| 852 | 852 | /// If the Decl has a value and it is a union, return it, |
| 853 | 853 | /// otherwise null. |
| 854 | pub fn getUnion(decl: *Decl) ?*Union { | |
| 854 | pub fn getUnion(decl: *Decl, mod: *Module) ?*Union { | |
| 855 | 855 | if (!decl.owns_tv) return null; |
| 856 | 856 | const ty = (decl.val.castTag(.ty) orelse return null).data; |
| 857 | const union_obj = (ty.cast(Type.Payload.Union) orelse return null).data; | |
| 858 | return union_obj; | |
| 857 | return mod.typeToUnion(ty); | |
| 859 | 858 | } |
| 860 | 859 | |
| 861 | 860 | /// If the Decl has a value and it is a function, return it, |
| ... | ... | @@ -896,10 +895,6 @@ pub const Decl = struct { |
| 896 | 895 | const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; |
| 897 | 896 | return enum_obj.namespace.toOptional(); |
| 898 | 897 | }, |
| 899 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 900 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 901 | return union_obj.namespace.toOptional(); | |
| 902 | }, | |
| 903 | 898 | |
| 904 | 899 | else => return .none, |
| 905 | 900 | } |
| ... | ... | @@ -907,6 +902,10 @@ pub const Decl = struct { |
| 907 | 902 | else => return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { |
| 908 | 903 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), |
| 909 | 904 | .struct_type => |struct_type| struct_type.namespace, |
| 905 | .union_type => |union_type| { | |
| 906 | const union_obj = mod.unionPtr(union_type.index); | |
| 907 | return union_obj.namespace.toOptional(); | |
| 908 | }, | |
| 910 | 909 | else => .none, |
| 911 | 910 | }, |
| 912 | 911 | } |
| ... | ... | @@ -1373,6 +1372,28 @@ pub const Union = struct { |
| 1373 | 1372 | requires_comptime: PropertyBoolean = .unknown, |
| 1374 | 1373 | assumed_runtime_bits: bool = false, |
| 1375 | 1374 | |
| 1375 | pub const Index = enum(u32) { | |
| 1376 | _, | |
| 1377 | ||
| 1378 | pub fn toOptional(i: Index) OptionalIndex { | |
| 1379 | return @intToEnum(OptionalIndex, @enumToInt(i)); | |
| 1380 | } | |
| 1381 | }; | |
| 1382 | ||
| 1383 | pub const OptionalIndex = enum(u32) { | |
| 1384 | none = std.math.maxInt(u32), | |
| 1385 | _, | |
| 1386 | ||
| 1387 | pub fn init(oi: ?Index) OptionalIndex { | |
| 1388 | return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none)); | |
| 1389 | } | |
| 1390 | ||
| 1391 | pub fn unwrap(oi: OptionalIndex) ?Index { | |
| 1392 | if (oi == .none) return null; | |
| 1393 | return @intToEnum(Index, @enumToInt(oi)); | |
| 1394 | } | |
| 1395 | }; | |
| 1396 | ||
| 1376 | 1397 | pub const Field = struct { |
| 1377 | 1398 | /// undefined until `status` is `have_field_types` or `have_layout`. |
| 1378 | 1399 | ty: Type, |
| ... | ... | @@ -3639,6 +3660,10 @@ pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace { |
| 3639 | 3660 | return mod.allocated_namespaces.at(@enumToInt(index)); |
| 3640 | 3661 | } |
| 3641 | 3662 | |
| 3663 | pub fn unionPtr(mod: *Module, index: Union.Index) *Union { | |
| 3664 | return mod.intern_pool.unionPtr(index); | |
| 3665 | } | |
| 3666 | ||
| 3642 | 3667 | pub fn structPtr(mod: *Module, index: Struct.Index) *Struct { |
| 3643 | 3668 | return mod.intern_pool.structPtr(index); |
| 3644 | 3669 | } |
| ... | ... | @@ -4112,7 +4137,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { |
| 4112 | 4137 | }; |
| 4113 | 4138 | } |
| 4114 | 4139 | |
| 4115 | if (decl.getUnion()) |union_obj| { | |
| 4140 | if (decl.getUnion(mod)) |union_obj| { | |
| 4116 | 4141 | union_obj.zir_index = inst_map.get(union_obj.zir_index) orelse { |
| 4117 | 4142 | try file.deleted_decls.append(gpa, decl_index); |
| 4118 | 4143 | continue; |
| ... | ... | @@ -5988,20 +6013,10 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { |
| 5988 | 6013 | decl.analysis = .outdated; |
| 5989 | 6014 | } |
| 5990 | 6015 | |
| 5991 | pub const CreateNamespaceOptions = struct { | |
| 5992 | parent: Namespace.OptionalIndex, | |
| 5993 | file_scope: *File, | |
| 5994 | ty: Type, | |
| 5995 | }; | |
| 5996 | ||
| 5997 | pub fn createNamespace(mod: *Module, options: CreateNamespaceOptions) !Namespace.Index { | |
| 6016 | pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index { | |
| 5998 | 6017 | if (mod.namespaces_free_list.popOrNull()) |index| return index; |
| 5999 | 6018 | const ptr = try mod.allocated_namespaces.addOne(mod.gpa); |
| 6000 | ptr.* = .{ | |
| 6001 | .parent = options.parent, | |
| 6002 | .file_scope = options.file_scope, | |
| 6003 | .ty = options.ty, | |
| 6004 | }; | |
| 6019 | ptr.* = initialization; | |
| 6005 | 6020 | return @intToEnum(Namespace.Index, mod.allocated_namespaces.len - 1); |
| 6006 | 6021 | } |
| 6007 | 6022 | |
| ... | ... | @@ -6021,6 +6036,14 @@ pub fn destroyStruct(mod: *Module, index: Struct.Index) void { |
| 6021 | 6036 | return mod.intern_pool.destroyStruct(mod.gpa, index); |
| 6022 | 6037 | } |
| 6023 | 6038 | |
| 6039 | pub fn createUnion(mod: *Module, initialization: Union) Allocator.Error!Union.Index { | |
| 6040 | return mod.intern_pool.createUnion(mod.gpa, initialization); | |
| 6041 | } | |
| 6042 | ||
| 6043 | pub fn destroyUnion(mod: *Module, index: Union.Index) void { | |
| 6044 | return mod.intern_pool.destroyUnion(mod.gpa, index); | |
| 6045 | } | |
| 6046 | ||
| 6024 | 6047 | pub fn allocateNewDecl( |
| 6025 | 6048 | mod: *Module, |
| 6026 | 6049 | namespace: Namespace.Index, |
| ... | ... | @@ -7068,6 +7091,15 @@ pub fn intValue_i64(mod: *Module, ty: Type, x: i64) Allocator.Error!Value { |
| 7068 | 7091 | return i.toValue(); |
| 7069 | 7092 | } |
| 7070 | 7093 | |
| 7094 | pub fn unionValue(mod: *Module, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value { | |
| 7095 | const i = try intern(mod, .{ .un = .{ | |
| 7096 | .ty = union_ty.ip_index, | |
| 7097 | .tag = tag.ip_index, | |
| 7098 | .val = val.ip_index, | |
| 7099 | } }); | |
| 7100 | return i.toValue(); | |
| 7101 | } | |
| 7102 | ||
| 7071 | 7103 | pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type { |
| 7072 | 7104 | return intType(mod, .unsigned, Type.smallestUnsignedBits(max)); |
| 7073 | 7105 | } |
| ... | ... | @@ -7276,3 +7308,8 @@ pub fn typeToStruct(mod: *Module, ty: Type) ?*Struct { |
| 7276 | 7308 | const struct_index = mod.intern_pool.indexToStruct(ty.ip_index).unwrap() orelse return null; |
| 7277 | 7309 | return mod.structPtr(struct_index); |
| 7278 | 7310 | } |
| 7311 | ||
| 7312 | pub fn typeToUnion(mod: *Module, ty: Type) ?*Union { | |
| 7313 | const union_index = mod.intern_pool.indexToUnion(ty.ip_index).unwrap() orelse return null; | |
| 7314 | return mod.unionPtr(union_index); | |
| 7315 | } |
src/Sema.zig+203-178| ... | ... | @@ -3123,6 +3123,8 @@ fn zirUnionDecl( |
| 3123 | 3123 | const tracy = trace(@src()); |
| 3124 | 3124 | defer tracy.end(); |
| 3125 | 3125 | |
| 3126 | const mod = sema.mod; | |
| 3127 | const gpa = sema.gpa; | |
| 3126 | 3128 | const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small); |
| 3127 | 3129 | var extra_index: usize = extended.operand; |
| 3128 | 3130 | |
| ... | ... | @@ -3142,49 +3144,57 @@ fn zirUnionDecl( |
| 3142 | 3144 | break :blk decls_len; |
| 3143 | 3145 | } else 0; |
| 3144 | 3146 | |
| 3145 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | |
| 3147 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); | |
| 3146 | 3148 | errdefer new_decl_arena.deinit(); |
| 3147 | const new_decl_arena_allocator = new_decl_arena.allocator(); | |
| 3148 | 3149 | |
| 3149 | const union_obj = try new_decl_arena_allocator.create(Module.Union); | |
| 3150 | const type_tag = if (small.has_tag_type or small.auto_enum_tag) | |
| 3151 | Type.Tag.union_tagged | |
| 3152 | else if (small.layout != .Auto) | |
| 3153 | Type.Tag.@"union" | |
| 3154 | else switch (block.sema.mod.optimizeMode()) { | |
| 3155 | .Debug, .ReleaseSafe => Type.Tag.union_safety_tagged, | |
| 3156 | .ReleaseFast, .ReleaseSmall => Type.Tag.@"union", | |
| 3157 | }; | |
| 3158 | const union_payload = try new_decl_arena_allocator.create(Type.Payload.Union); | |
| 3159 | union_payload.* = .{ | |
| 3160 | .base = .{ .tag = type_tag }, | |
| 3161 | .data = union_obj, | |
| 3162 | }; | |
| 3163 | const union_ty = Type.initPayload(&union_payload.base); | |
| 3164 | const union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty); | |
| 3165 | const mod = sema.mod; | |
| 3150 | // Because these three things each reference each other, `undefined` | |
| 3151 | // placeholders are used before being set after the union type gains an | |
| 3152 | // InternPool index. | |
| 3153 | ||
| 3166 | 3154 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 3167 | 3155 | .ty = Type.type, |
| 3168 | .val = union_val, | |
| 3156 | .val = undefined, | |
| 3169 | 3157 | }, small.name_strategy, "union", inst); |
| 3170 | 3158 | const new_decl = mod.declPtr(new_decl_index); |
| 3171 | 3159 | new_decl.owns_tv = true; |
| 3172 | 3160 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3173 | union_obj.* = .{ | |
| 3161 | ||
| 3162 | const new_namespace_index = try mod.createNamespace(.{ | |
| 3163 | .parent = block.namespace.toOptional(), | |
| 3164 | .ty = undefined, | |
| 3165 | .file_scope = block.getFileScope(mod), | |
| 3166 | }); | |
| 3167 | const new_namespace = mod.namespacePtr(new_namespace_index); | |
| 3168 | errdefer mod.destroyNamespace(new_namespace_index); | |
| 3169 | ||
| 3170 | const union_index = try mod.createUnion(.{ | |
| 3174 | 3171 | .owner_decl = new_decl_index, |
| 3175 | 3172 | .tag_ty = Type.null, |
| 3176 | 3173 | .fields = .{}, |
| 3177 | 3174 | .zir_index = inst, |
| 3178 | 3175 | .layout = small.layout, |
| 3179 | 3176 | .status = .none, |
| 3180 | .namespace = try mod.createNamespace(.{ | |
| 3181 | .parent = block.namespace.toOptional(), | |
| 3182 | .ty = union_ty, | |
| 3183 | .file_scope = block.getFileScope(mod), | |
| 3184 | }), | |
| 3185 | }; | |
| 3177 | .namespace = new_namespace_index, | |
| 3178 | }); | |
| 3179 | errdefer mod.destroyUnion(union_index); | |
| 3180 | ||
| 3181 | const union_ty = try mod.intern_pool.get(gpa, .{ .union_type = .{ | |
| 3182 | .index = union_index, | |
| 3183 | .runtime_tag = if (small.has_tag_type or small.auto_enum_tag) | |
| 3184 | .tagged | |
| 3185 | else if (small.layout != .Auto) | |
| 3186 | .none | |
| 3187 | else switch (block.sema.mod.optimizeMode()) { | |
| 3188 | .Debug, .ReleaseSafe => .safety, | |
| 3189 | .ReleaseFast, .ReleaseSmall => .none, | |
| 3190 | }, | |
| 3191 | } }); | |
| 3192 | errdefer mod.intern_pool.remove(union_ty); | |
| 3193 | ||
| 3194 | new_decl.val = union_ty.toValue(); | |
| 3195 | new_namespace.ty = union_ty.toType(); | |
| 3186 | 3196 | |
| 3187 | _ = try mod.scanNamespace(union_obj.namespace, extra_index, decls_len, new_decl); | |
| 3197 | _ = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl); | |
| 3188 | 3198 | |
| 3189 | 3199 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 3190 | 3200 | return sema.analyzeDeclVal(block, src, new_decl_index); |
| ... | ... | @@ -4246,6 +4256,8 @@ fn validateUnionInit( |
| 4246 | 4256 | instrs: []const Zir.Inst.Index, |
| 4247 | 4257 | union_ptr: Air.Inst.Ref, |
| 4248 | 4258 | ) CompileError!void { |
| 4259 | const mod = sema.mod; | |
| 4260 | ||
| 4249 | 4261 | if (instrs.len != 1) { |
| 4250 | 4262 | const msg = msg: { |
| 4251 | 4263 | const msg = try sema.errMsg( |
| ... | ... | @@ -4343,7 +4355,7 @@ fn validateUnionInit( |
| 4343 | 4355 | break; |
| 4344 | 4356 | } |
| 4345 | 4357 | |
| 4346 | const tag_ty = union_ty.unionTagTypeHypothetical(); | |
| 4358 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); | |
| 4347 | 4359 | const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?); |
| 4348 | 4360 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); |
| 4349 | 4361 | |
| ... | ... | @@ -8273,7 +8285,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 8273 | 8285 | .Enum => operand, |
| 8274 | 8286 | .Union => blk: { |
| 8275 | 8287 | const union_ty = try sema.resolveTypeFields(operand_ty); |
| 8276 | const tag_ty = union_ty.unionTagType() orelse { | |
| 8288 | const tag_ty = union_ty.unionTagType(mod) orelse { | |
| 8277 | 8289 | return sema.fail( |
| 8278 | 8290 | block, |
| 8279 | 8291 | operand_src, |
| ... | ... | @@ -10158,7 +10170,7 @@ fn zirSwitchCapture( |
| 10158 | 10170 | const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable; |
| 10159 | 10171 | if (operand_ty.zigTypeTag(mod) == .Union) { |
| 10160 | 10172 | const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, sema.mod).?); |
| 10161 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; | |
| 10173 | const union_obj = mod.typeToUnion(operand_ty).?; | |
| 10162 | 10174 | const field_ty = union_obj.fields.values()[field_index].ty; |
| 10163 | 10175 | if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_val| { |
| 10164 | 10176 | if (is_ref) { |
| ... | ... | @@ -10229,7 +10241,7 @@ fn zirSwitchCapture( |
| 10229 | 10241 | |
| 10230 | 10242 | switch (operand_ty.zigTypeTag(mod)) { |
| 10231 | 10243 | .Union => { |
| 10232 | const union_obj = operand_ty.cast(Type.Payload.Union).?.data; | |
| 10244 | const union_obj = mod.typeToUnion(operand_ty).?; | |
| 10233 | 10245 | const first_item = try sema.resolveInst(items[0]); |
| 10234 | 10246 | // Previous switch validation ensured this will succeed |
| 10235 | 10247 | const first_item_val = sema.resolveConstValue(block, .unneeded, first_item, "") catch unreachable; |
| ... | ... | @@ -10403,7 +10415,7 @@ fn zirSwitchCond( |
| 10403 | 10415 | |
| 10404 | 10416 | .Union => { |
| 10405 | 10417 | const union_ty = try sema.resolveTypeFields(operand_ty); |
| 10406 | const enum_ty = union_ty.unionTagType() orelse { | |
| 10418 | const enum_ty = union_ty.unionTagType(mod) orelse { | |
| 10407 | 10419 | const msg = msg: { |
| 10408 | 10420 | const msg = try sema.errMsg(block, src, "switch on union with no attached enum", .{}); |
| 10409 | 10421 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -11627,7 +11639,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11627 | 11639 | const analyze_body = if (union_originally and !special.is_inline) |
| 11628 | 11640 | for (seen_enum_fields, 0..) |seen_field, index| { |
| 11629 | 11641 | if (seen_field != null) continue; |
| 11630 | const union_obj = maybe_union_ty.cast(Type.Payload.Union).?.data; | |
| 11642 | const union_obj = mod.typeToUnion(maybe_union_ty).?; | |
| 11631 | 11643 | const field_ty = union_obj.fields.values()[index].ty; |
| 11632 | 11644 | if (field_ty.zigTypeTag(mod) != .NoReturn) break true; |
| 11633 | 11645 | } else false |
| ... | ... | @@ -12068,7 +12080,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12068 | 12080 | } |
| 12069 | 12081 | break :hf switch (ty.zigTypeTag(mod)) { |
| 12070 | 12082 | .Struct => ty.structFields(mod).contains(field_name), |
| 12071 | .Union => ty.unionFields().contains(field_name), | |
| 12083 | .Union => ty.unionFields(mod).contains(field_name), | |
| 12072 | 12084 | .Enum => ty.enumFields().contains(field_name), |
| 12073 | 12085 | .Array => mem.eql(u8, field_name, "len"), |
| 12074 | 12086 | else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{ |
| ... | ... | @@ -15415,7 +15427,7 @@ fn analyzeCmpUnionTag( |
| 15415 | 15427 | ) CompileError!Air.Inst.Ref { |
| 15416 | 15428 | const mod = sema.mod; |
| 15417 | 15429 | const union_ty = try sema.resolveTypeFields(sema.typeOf(un)); |
| 15418 | const union_tag_ty = union_ty.unionTagType() orelse { | |
| 15430 | const union_tag_ty = union_ty.unionTagType(mod) orelse { | |
| 15419 | 15431 | const msg = msg: { |
| 15420 | 15432 | const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); |
| 15421 | 15433 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -16403,7 +16415,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16403 | 16415 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout |
| 16404 | 16416 | const layout = union_ty.containerLayout(mod); |
| 16405 | 16417 | |
| 16406 | const union_fields = union_ty.unionFields(); | |
| 16418 | const union_fields = union_ty.unionFields(mod); | |
| 16407 | 16419 | const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count()); |
| 16408 | 16420 | |
| 16409 | 16421 | for (union_field_vals, 0..) |*field_val, i| { |
| ... | ... | @@ -16458,7 +16470,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16458 | 16470 | |
| 16459 | 16471 | const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespace(mod)); |
| 16460 | 16472 | |
| 16461 | const enum_tag_ty_val = if (union_ty.unionTagType()) |tag_ty| v: { | |
| 16473 | const enum_tag_ty_val = if (union_ty.unionTagType(mod)) |tag_ty| v: { | |
| 16462 | 16474 | const ty_val = try Value.Tag.ty.create(sema.arena, tag_ty); |
| 16463 | 16475 | break :v try Value.Tag.opt_payload.create(sema.arena, ty_val); |
| 16464 | 16476 | } else Value.null; |
| ... | ... | @@ -17877,12 +17889,13 @@ fn unionInit( |
| 17877 | 17889 | field_name: []const u8, |
| 17878 | 17890 | field_src: LazySrcLoc, |
| 17879 | 17891 | ) CompileError!Air.Inst.Ref { |
| 17892 | const mod = sema.mod; | |
| 17880 | 17893 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); |
| 17881 | const field = union_ty.unionFields().values()[field_index]; | |
| 17894 | const field = union_ty.unionFields(mod).values()[field_index]; | |
| 17882 | 17895 | const init = try sema.coerce(block, field.ty, uncasted_init, init_src); |
| 17883 | 17896 | |
| 17884 | 17897 | if (try sema.resolveMaybeUndefVal(init)) |init_val| { |
| 17885 | const tag_ty = union_ty.unionTagTypeHypothetical(); | |
| 17898 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); | |
| 17886 | 17899 | const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?); |
| 17887 | 17900 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); |
| 17888 | 17901 | return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{ |
| ... | ... | @@ -17983,7 +17996,7 @@ fn zirStructInit( |
| 17983 | 17996 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 17984 | 17997 | const field_name = sema.code.nullTerminatedString(field_type_extra.name_start); |
| 17985 | 17998 | const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src); |
| 17986 | const tag_ty = resolved_ty.unionTagTypeHypothetical(); | |
| 17999 | const tag_ty = resolved_ty.unionTagTypeHypothetical(mod); | |
| 17987 | 18000 | const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?); |
| 17988 | 18001 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); |
| 17989 | 18002 | |
| ... | ... | @@ -18006,7 +18019,7 @@ fn zirStructInit( |
| 18006 | 18019 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 18007 | 18020 | const field_ptr = try sema.unionFieldPtr(block, field_src, alloc, field_name, field_src, resolved_ty, true); |
| 18008 | 18021 | try sema.storePtr(block, src, field_ptr, init_inst); |
| 18009 | const new_tag = try sema.addConstant(resolved_ty.unionTagTypeHypothetical(), tag_val); | |
| 18022 | const new_tag = try sema.addConstant(resolved_ty.unionTagTypeHypothetical(mod), tag_val); | |
| 18010 | 18023 | _ = try block.addBinOp(.set_union_tag, alloc, new_tag); |
| 18011 | 18024 | return sema.makePtrConst(block, alloc); |
| 18012 | 18025 | } |
| ... | ... | @@ -18544,7 +18557,7 @@ fn fieldType( |
| 18544 | 18557 | return sema.addType(field.ty); |
| 18545 | 18558 | }, |
| 18546 | 18559 | .Union => { |
| 18547 | const union_obj = cur_ty.cast(Type.Payload.Union).?.data; | |
| 18560 | const union_obj = mod.typeToUnion(cur_ty).?; | |
| 18548 | 18561 | const field = union_obj.fields.get(field_name) orelse |
| 18549 | 18562 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 18550 | 18563 | return sema.addType(field.ty); |
| ... | ... | @@ -18726,7 +18739,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18726 | 18739 | return sema.addStrLit(block, bytes); |
| 18727 | 18740 | }, |
| 18728 | 18741 | .Enum => operand_ty, |
| 18729 | .Union => operand_ty.unionTagType() orelse { | |
| 18742 | .Union => operand_ty.unionTagType(mod) orelse { | |
| 18730 | 18743 | const msg = msg: { |
| 18731 | 18744 | const msg = try sema.errMsg(block, src, "union '{}' is untagged", .{ |
| 18732 | 18745 | operand_ty.fmt(sema.mod), |
| ... | ... | @@ -19245,42 +19258,53 @@ fn zirReify( |
| 19245 | 19258 | errdefer new_decl_arena.deinit(); |
| 19246 | 19259 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| 19247 | 19260 | |
| 19248 | const union_obj = try new_decl_arena_allocator.create(Module.Union); | |
| 19249 | const type_tag = if (!tag_type_val.isNull(mod)) | |
| 19250 | Type.Tag.union_tagged | |
| 19251 | else if (layout != .Auto) | |
| 19252 | Type.Tag.@"union" | |
| 19253 | else switch (mod.optimizeMode()) { | |
| 19254 | .Debug, .ReleaseSafe => Type.Tag.union_safety_tagged, | |
| 19255 | .ReleaseFast, .ReleaseSmall => Type.Tag.@"union", | |
| 19256 | }; | |
| 19257 | const union_payload = try new_decl_arena_allocator.create(Type.Payload.Union); | |
| 19258 | union_payload.* = .{ | |
| 19259 | .base = .{ .tag = type_tag }, | |
| 19260 | .data = union_obj, | |
| 19261 | }; | |
| 19262 | const union_ty = Type.initPayload(&union_payload.base); | |
| 19263 | const new_union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty); | |
| 19261 | // Because these three things each reference each other, `undefined` | |
| 19262 | // placeholders are used before being set after the union type gains an | |
| 19263 | // InternPool index. | |
| 19264 | ||
| 19264 | 19265 | const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ |
| 19265 | 19266 | .ty = Type.type, |
| 19266 | .val = new_union_val, | |
| 19267 | .val = undefined, | |
| 19267 | 19268 | }, name_strategy, "union", inst); |
| 19268 | 19269 | const new_decl = mod.declPtr(new_decl_index); |
| 19269 | 19270 | new_decl.owns_tv = true; |
| 19270 | 19271 | errdefer mod.abortAnonDecl(new_decl_index); |
| 19271 | union_obj.* = .{ | |
| 19272 | ||
| 19273 | const new_namespace_index = try mod.createNamespace(.{ | |
| 19274 | .parent = block.namespace.toOptional(), | |
| 19275 | .ty = undefined, | |
| 19276 | .file_scope = block.getFileScope(mod), | |
| 19277 | }); | |
| 19278 | const new_namespace = mod.namespacePtr(new_namespace_index); | |
| 19279 | errdefer mod.destroyNamespace(new_namespace_index); | |
| 19280 | ||
| 19281 | const union_index = try mod.createUnion(.{ | |
| 19272 | 19282 | .owner_decl = new_decl_index, |
| 19273 | 19283 | .tag_ty = Type.null, |
| 19274 | 19284 | .fields = .{}, |
| 19275 | 19285 | .zir_index = inst, |
| 19276 | 19286 | .layout = layout, |
| 19277 | 19287 | .status = .have_field_types, |
| 19278 | .namespace = try mod.createNamespace(.{ | |
| 19279 | .parent = block.namespace.toOptional(), | |
| 19280 | .ty = union_ty, | |
| 19281 | .file_scope = block.getFileScope(mod), | |
| 19282 | }), | |
| 19283 | }; | |
| 19288 | .namespace = new_namespace_index, | |
| 19289 | }); | |
| 19290 | const union_obj = mod.unionPtr(union_index); | |
| 19291 | errdefer mod.destroyUnion(union_index); | |
| 19292 | ||
| 19293 | const union_ty = try mod.intern_pool.get(gpa, .{ .union_type = .{ | |
| 19294 | .index = union_index, | |
| 19295 | .runtime_tag = if (!tag_type_val.isNull(mod)) | |
| 19296 | .tagged | |
| 19297 | else if (layout != .Auto) | |
| 19298 | .none | |
| 19299 | else switch (mod.optimizeMode()) { | |
| 19300 | .Debug, .ReleaseSafe => .safety, | |
| 19301 | .ReleaseFast, .ReleaseSmall => .none, | |
| 19302 | }, | |
| 19303 | } }); | |
| 19304 | errdefer mod.intern_pool.remove(union_ty); | |
| 19305 | ||
| 19306 | new_decl.val = union_ty.toValue(); | |
| 19307 | new_namespace.ty = union_ty.toType(); | |
| 19284 | 19308 | |
| 19285 | 19309 | // Tag type |
| 19286 | 19310 | var tag_ty_field_names: ?Module.EnumFull.NameMap = null; |
| ... | ... | @@ -21981,8 +22005,8 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 21981 | 22005 | ptr_ty_data.@"align" = blk: { |
| 21982 | 22006 | if (mod.typeToStruct(parent_ty)) |struct_obj| { |
| 21983 | 22007 | break :blk struct_obj.fields.values()[field_index].abi_align; |
| 21984 | } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| { | |
| 21985 | break :blk union_obj.data.fields.values()[field_index].abi_align; | |
| 22008 | } else if (mod.typeToUnion(parent_ty)) |union_obj| { | |
| 22009 | break :blk union_obj.fields.values()[field_index].abi_align; | |
| 21986 | 22010 | } else { |
| 21987 | 22011 | break :blk 0; |
| 21988 | 22012 | } |
| ... | ... | @@ -23443,8 +23467,7 @@ fn explainWhyTypeIsComptimeInner( |
| 23443 | 23467 | .Union => { |
| 23444 | 23468 | if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return; |
| 23445 | 23469 | |
| 23446 | if (ty.cast(Type.Payload.Union)) |payload| { | |
| 23447 | const union_obj = payload.data; | |
| 23470 | if (mod.typeToUnion(ty)) |union_obj| { | |
| 23448 | 23471 | for (union_obj.fields.values(), 0..) |field, i| { |
| 23449 | 23472 | const field_src_loc = union_obj.fieldSrcLoc(sema.mod, .{ |
| 23450 | 23473 | .index = i, |
| ... | ... | @@ -24144,7 +24167,7 @@ fn fieldVal( |
| 24144 | 24167 | } |
| 24145 | 24168 | } |
| 24146 | 24169 | const union_ty = try sema.resolveTypeFields(child_type); |
| 24147 | if (union_ty.unionTagType()) |enum_ty| { | |
| 24170 | if (union_ty.unionTagType(mod)) |enum_ty| { | |
| 24148 | 24171 | if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| { |
| 24149 | 24172 | const field_index = @intCast(u32, field_index_usize); |
| 24150 | 24173 | return sema.addConstant( |
| ... | ... | @@ -24358,7 +24381,7 @@ fn fieldPtr( |
| 24358 | 24381 | } |
| 24359 | 24382 | } |
| 24360 | 24383 | const union_ty = try sema.resolveTypeFields(child_type); |
| 24361 | if (union_ty.unionTagType()) |enum_ty| { | |
| 24384 | if (union_ty.unionTagType(mod)) |enum_ty| { | |
| 24362 | 24385 | if (enum_ty.enumFieldIndex(field_name)) |field_index| { |
| 24363 | 24386 | const field_index_u32 = @intCast(u32, field_index); |
| 24364 | 24387 | var anon_decl = try block.startAnonDecl(); |
| ... | ... | @@ -24489,7 +24512,7 @@ fn fieldCallBind( |
| 24489 | 24512 | }, |
| 24490 | 24513 | .Union => { |
| 24491 | 24514 | const union_ty = try sema.resolveTypeFields(concrete_ty); |
| 24492 | const fields = union_ty.unionFields(); | |
| 24515 | const fields = union_ty.unionFields(mod); | |
| 24493 | 24516 | const field_index_usize = fields.getIndex(field_name) orelse break :find_field; |
| 24494 | 24517 | const field_index = @intCast(u32, field_index_usize); |
| 24495 | 24518 | const field = fields.values()[field_index]; |
| ... | ... | @@ -24964,7 +24987,7 @@ fn unionFieldPtr( |
| 24964 | 24987 | |
| 24965 | 24988 | const union_ptr_ty = sema.typeOf(union_ptr); |
| 24966 | 24989 | const union_ty = try sema.resolveTypeFields(unresolved_union_ty); |
| 24967 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 24990 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 24968 | 24991 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 24969 | 24992 | const field = union_obj.fields.values()[field_index]; |
| 24970 | 24993 | const ptr_field_ty = try Type.ptr(arena, mod, .{ |
| ... | ... | @@ -25028,7 +25051,7 @@ fn unionFieldPtr( |
| 25028 | 25051 | |
| 25029 | 25052 | try sema.requireRuntimeBlock(block, src, null); |
| 25030 | 25053 | if (!initializing and union_obj.layout == .Auto and block.wantSafety() and |
| 25031 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) | |
| 25054 | union_ty.unionTagTypeSafety(mod) != null and union_obj.fields.count() > 1) | |
| 25032 | 25055 | { |
| 25033 | 25056 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); |
| 25034 | 25057 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); |
| ... | ... | @@ -25057,7 +25080,7 @@ fn unionFieldVal( |
| 25057 | 25080 | assert(unresolved_union_ty.zigTypeTag(mod) == .Union); |
| 25058 | 25081 | |
| 25059 | 25082 | const union_ty = try sema.resolveTypeFields(unresolved_union_ty); |
| 25060 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 25083 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 25061 | 25084 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 25062 | 25085 | const field = union_obj.fields.values()[field_index]; |
| 25063 | 25086 | const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?); |
| ... | ... | @@ -25103,7 +25126,7 @@ fn unionFieldVal( |
| 25103 | 25126 | |
| 25104 | 25127 | try sema.requireRuntimeBlock(block, src, null); |
| 25105 | 25128 | if (union_obj.layout == .Auto and block.wantSafety() and |
| 25106 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) | |
| 25129 | union_ty.unionTagTypeSafety(mod) != null and union_obj.fields.count() > 1) | |
| 25107 | 25130 | { |
| 25108 | 25131 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); |
| 25109 | 25132 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); |
| ... | ... | @@ -26189,7 +26212,7 @@ fn coerceExtra( |
| 26189 | 26212 | }, |
| 26190 | 26213 | .Union => blk: { |
| 26191 | 26214 | // union to its own tag type |
| 26192 | const union_tag_ty = inst_ty.unionTagType() orelse break :blk; | |
| 26215 | const union_tag_ty = inst_ty.unionTagType(mod) orelse break :blk; | |
| 26193 | 26216 | if (union_tag_ty.eql(dest_ty, sema.mod)) { |
| 26194 | 26217 | return sema.unionToTag(block, dest_ty, inst, inst_src); |
| 26195 | 26218 | } |
| ... | ... | @@ -28622,7 +28645,7 @@ fn coerceEnumToUnion( |
| 28622 | 28645 | const mod = sema.mod; |
| 28623 | 28646 | const inst_ty = sema.typeOf(inst); |
| 28624 | 28647 | |
| 28625 | const tag_ty = union_ty.unionTagType() orelse { | |
| 28648 | const tag_ty = union_ty.unionTagType(mod) orelse { | |
| 28626 | 28649 | const msg = msg: { |
| 28627 | 28650 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ |
| 28628 | 28651 | union_ty.fmt(sema.mod), inst_ty.fmt(sema.mod), |
| ... | ... | @@ -28649,7 +28672,7 @@ fn coerceEnumToUnion( |
| 28649 | 28672 | return sema.failWithOwnedErrorMsg(msg); |
| 28650 | 28673 | }; |
| 28651 | 28674 | |
| 28652 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 28675 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 28653 | 28676 | const field = union_obj.fields.values()[field_index]; |
| 28654 | 28677 | const field_ty = try sema.resolveTypeFields(field.ty); |
| 28655 | 28678 | if (field_ty.zigTypeTag(mod) == .NoReturn) { |
| ... | ... | @@ -28679,10 +28702,7 @@ fn coerceEnumToUnion( |
| 28679 | 28702 | return sema.failWithOwnedErrorMsg(msg); |
| 28680 | 28703 | }; |
| 28681 | 28704 | |
| 28682 | return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{ | |
| 28683 | .tag = val, | |
| 28684 | .val = opv, | |
| 28685 | })); | |
| 28705 | return sema.addConstant(union_ty, try mod.unionValue(union_ty, val, opv)); | |
| 28686 | 28706 | } |
| 28687 | 28707 | |
| 28688 | 28708 | try sema.requireRuntimeBlock(block, inst_src, null); |
| ... | ... | @@ -28699,7 +28719,7 @@ fn coerceEnumToUnion( |
| 28699 | 28719 | return sema.failWithOwnedErrorMsg(msg); |
| 28700 | 28720 | } |
| 28701 | 28721 | |
| 28702 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 28722 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 28703 | 28723 | { |
| 28704 | 28724 | var msg: ?*Module.ErrorMsg = null; |
| 28705 | 28725 | errdefer if (msg) |some| some.destroy(sema.gpa); |
| ... | ... | @@ -29350,10 +29370,13 @@ fn analyzeRef( |
| 29350 | 29370 | const operand_ty = sema.typeOf(operand); |
| 29351 | 29371 | |
| 29352 | 29372 | if (try sema.resolveMaybeUndefVal(operand)) |val| { |
| 29353 | switch (val.tag()) { | |
| 29354 | .extern_fn, .function => { | |
| 29355 | const decl_index = val.pointerDecl().?; | |
| 29356 | return sema.analyzeDeclRef(decl_index); | |
| 29373 | switch (val.ip_index) { | |
| 29374 | .none => switch (val.tag()) { | |
| 29375 | .extern_fn, .function => { | |
| 29376 | const decl_index = val.pointerDecl().?; | |
| 29377 | return sema.analyzeDeclRef(decl_index); | |
| 29378 | }, | |
| 29379 | else => {}, | |
| 29357 | 29380 | }, |
| 29358 | 29381 | else => {}, |
| 29359 | 29382 | } |
| ... | ... | @@ -31523,8 +31546,9 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void |
| 31523 | 31546 | } |
| 31524 | 31547 | |
| 31525 | 31548 | fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31549 | const mod = sema.mod; | |
| 31526 | 31550 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31527 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; | |
| 31551 | const union_obj = mod.typeToUnion(resolved_ty).?; | |
| 31528 | 31552 | switch (union_obj.status) { |
| 31529 | 31553 | .none, .have_field_types => {}, |
| 31530 | 31554 | .field_types_wip, .layout_wip => { |
| ... | ... | @@ -31617,27 +31641,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31617 | 31641 | return false; |
| 31618 | 31642 | }, |
| 31619 | 31643 | |
| 31620 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 31621 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 31622 | switch (union_obj.requires_comptime) { | |
| 31623 | .no, .wip => return false, | |
| 31624 | .yes => return true, | |
| 31625 | .unknown => { | |
| 31626 | var requires_comptime = false; | |
| 31627 | union_obj.requires_comptime = .wip; | |
| 31628 | for (union_obj.fields.values()) |field| { | |
| 31629 | if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true; | |
| 31630 | } | |
| 31631 | if (requires_comptime) { | |
| 31632 | union_obj.requires_comptime = .yes; | |
| 31633 | } else { | |
| 31634 | union_obj.requires_comptime = .no; | |
| 31635 | } | |
| 31636 | return requires_comptime; | |
| 31637 | }, | |
| 31638 | } | |
| 31639 | }, | |
| 31640 | ||
| 31641 | 31644 | .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()), |
| 31642 | 31645 | .anyframe_T => { |
| 31643 | 31646 | const child_ty = ty.castTag(.anyframe_T).?.data; |
| ... | ... | @@ -31734,10 +31737,31 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 31734 | 31737 | } |
| 31735 | 31738 | }, |
| 31736 | 31739 | |
| 31737 | .union_type => @panic("TODO"), | |
| 31740 | .union_type => |union_type| { | |
| 31741 | const union_obj = mod.unionPtr(union_type.index); | |
| 31742 | switch (union_obj.requires_comptime) { | |
| 31743 | .no, .wip => return false, | |
| 31744 | .yes => return true, | |
| 31745 | .unknown => { | |
| 31746 | var requires_comptime = false; | |
| 31747 | union_obj.requires_comptime = .wip; | |
| 31748 | for (union_obj.fields.values()) |field| { | |
| 31749 | if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true; | |
| 31750 | } | |
| 31751 | if (requires_comptime) { | |
| 31752 | union_obj.requires_comptime = .yes; | |
| 31753 | } else { | |
| 31754 | union_obj.requires_comptime = .no; | |
| 31755 | } | |
| 31756 | return requires_comptime; | |
| 31757 | }, | |
| 31758 | } | |
| 31759 | }, | |
| 31760 | ||
| 31738 | 31761 | .opaque_type => false, |
| 31739 | 31762 | |
| 31740 | 31763 | // values, not types |
| 31764 | .un => unreachable, | |
| 31741 | 31765 | .simple_value => unreachable, |
| 31742 | 31766 | .extern_func => unreachable, |
| 31743 | 31767 | .int => unreachable, |
| ... | ... | @@ -31829,8 +31853,9 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void { |
| 31829 | 31853 | fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void { |
| 31830 | 31854 | try sema.resolveUnionLayout(ty); |
| 31831 | 31855 | |
| 31856 | const mod = sema.mod; | |
| 31832 | 31857 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31833 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; | |
| 31858 | const union_obj = mod.typeToUnion(resolved_ty).?; | |
| 31834 | 31859 | switch (union_obj.status) { |
| 31835 | 31860 | .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {}, |
| 31836 | 31861 | .fully_resolved_wip, .fully_resolved => return, |
| ... | ... | @@ -31858,15 +31883,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { |
| 31858 | 31883 | const mod = sema.mod; |
| 31859 | 31884 | |
| 31860 | 31885 | switch (ty.ip_index) { |
| 31861 | .none => switch (ty.tag()) { | |
| 31862 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 31863 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 31864 | try sema.resolveTypeFieldsUnion(ty, union_obj); | |
| 31865 | return ty; | |
| 31866 | }, | |
| 31867 | ||
| 31868 | else => return ty, | |
| 31869 | }, | |
| 31886 | // TODO: After the InternPool transition is complete, change this to `unreachable`. | |
| 31887 | .none => return ty, | |
| 31870 | 31888 | |
| 31871 | 31889 | .u1_type, |
| 31872 | 31890 | .u8_type, |
| ... | ... | @@ -31957,7 +31975,12 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { |
| 31957 | 31975 | try sema.resolveTypeFieldsStruct(ty, struct_obj); |
| 31958 | 31976 | return ty; |
| 31959 | 31977 | }, |
| 31960 | .union_type => @panic("TODO"), | |
| 31978 | .union_type => |union_type| { | |
| 31979 | const union_obj = mod.unionPtr(union_type.index); | |
| 31980 | try sema.resolveTypeFieldsUnion(ty, union_obj); | |
| 31981 | return ty; | |
| 31982 | }, | |
| 31983 | ||
| 31961 | 31984 | else => return ty, |
| 31962 | 31985 | }, |
| 31963 | 31986 | } |
| ... | ... | @@ -33123,32 +33146,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33123 | 33146 | return null; |
| 33124 | 33147 | } |
| 33125 | 33148 | }, |
| 33126 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 33127 | const resolved_ty = try sema.resolveTypeFields(ty); | |
| 33128 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; | |
| 33129 | const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse | |
| 33130 | return null; | |
| 33131 | const fields = union_obj.fields.values(); | |
| 33132 | if (fields.len == 0) return Value.@"unreachable"; | |
| 33133 | const only_field = fields[0]; | |
| 33134 | if (only_field.ty.eql(resolved_ty, sema.mod)) { | |
| 33135 | const msg = try Module.ErrorMsg.create( | |
| 33136 | sema.gpa, | |
| 33137 | union_obj.srcLoc(sema.mod), | |
| 33138 | "union '{}' depends on itself", | |
| 33139 | .{ty.fmt(sema.mod)}, | |
| 33140 | ); | |
| 33141 | try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{}); | |
| 33142 | return sema.failWithOwnedErrorMsg(msg); | |
| 33143 | } | |
| 33144 | const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse | |
| 33145 | return null; | |
| 33146 | // TODO make this not allocate. | |
| 33147 | return try Value.Tag.@"union".create(sema.arena, .{ | |
| 33148 | .tag = tag_val, | |
| 33149 | .val = val_val, | |
| 33150 | }); | |
| 33151 | }, | |
| 33152 | 33149 | |
| 33153 | 33150 | .array => { |
| 33154 | 33151 | if (ty.arrayLen(mod) == 0) |
| ... | ... | @@ -33268,10 +33265,37 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33268 | 33265 | return empty.toValue(); |
| 33269 | 33266 | }, |
| 33270 | 33267 | |
| 33271 | .union_type => @panic("TODO"), | |
| 33268 | .union_type => |union_type| { | |
| 33269 | const resolved_ty = try sema.resolveTypeFields(ty); | |
| 33270 | const union_obj = mod.unionPtr(union_type.index); | |
| 33271 | const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse | |
| 33272 | return null; | |
| 33273 | const fields = union_obj.fields.values(); | |
| 33274 | if (fields.len == 0) return Value.@"unreachable"; | |
| 33275 | const only_field = fields[0]; | |
| 33276 | if (only_field.ty.eql(resolved_ty, sema.mod)) { | |
| 33277 | const msg = try Module.ErrorMsg.create( | |
| 33278 | sema.gpa, | |
| 33279 | union_obj.srcLoc(sema.mod), | |
| 33280 | "union '{}' depends on itself", | |
| 33281 | .{ty.fmt(sema.mod)}, | |
| 33282 | ); | |
| 33283 | try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{}); | |
| 33284 | return sema.failWithOwnedErrorMsg(msg); | |
| 33285 | } | |
| 33286 | const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse | |
| 33287 | return null; | |
| 33288 | const only = try mod.intern(.{ .un = .{ | |
| 33289 | .ty = resolved_ty.ip_index, | |
| 33290 | .tag = tag_val.ip_index, | |
| 33291 | .val = val_val.ip_index, | |
| 33292 | } }); | |
| 33293 | return only.toValue(); | |
| 33294 | }, | |
| 33272 | 33295 | .opaque_type => null, |
| 33273 | 33296 | |
| 33274 | 33297 | // values, not types |
| 33298 | .un => unreachable, | |
| 33275 | 33299 | .simple_value => unreachable, |
| 33276 | 33300 | .extern_func => unreachable, |
| 33277 | 33301 | .int => unreachable, |
| ... | ... | @@ -33710,30 +33734,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33710 | 33734 | return false; |
| 33711 | 33735 | }, |
| 33712 | 33736 | |
| 33713 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 33714 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 33715 | switch (union_obj.requires_comptime) { | |
| 33716 | .no, .wip => return false, | |
| 33717 | .yes => return true, | |
| 33718 | .unknown => { | |
| 33719 | if (union_obj.status == .field_types_wip) | |
| 33720 | return false; | |
| 33721 | ||
| 33722 | try sema.resolveTypeFieldsUnion(ty, union_obj); | |
| 33723 | ||
| 33724 | union_obj.requires_comptime = .wip; | |
| 33725 | for (union_obj.fields.values()) |field| { | |
| 33726 | if (try sema.typeRequiresComptime(field.ty)) { | |
| 33727 | union_obj.requires_comptime = .yes; | |
| 33728 | return true; | |
| 33729 | } | |
| 33730 | } | |
| 33731 | union_obj.requires_comptime = .no; | |
| 33732 | return false; | |
| 33733 | }, | |
| 33734 | } | |
| 33735 | }, | |
| 33736 | ||
| 33737 | 33737 | .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()), |
| 33738 | 33738 | .anyframe_T => { |
| 33739 | 33739 | const child_ty = ty.castTag(.anyframe_T).?.data; |
| ... | ... | @@ -33837,10 +33837,34 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33837 | 33837 | } |
| 33838 | 33838 | }, |
| 33839 | 33839 | |
| 33840 | .union_type => @panic("TODO"), | |
| 33840 | .union_type => |union_type| { | |
| 33841 | const union_obj = mod.unionPtr(union_type.index); | |
| 33842 | switch (union_obj.requires_comptime) { | |
| 33843 | .no, .wip => return false, | |
| 33844 | .yes => return true, | |
| 33845 | .unknown => { | |
| 33846 | if (union_obj.status == .field_types_wip) | |
| 33847 | return false; | |
| 33848 | ||
| 33849 | try sema.resolveTypeFieldsUnion(ty, union_obj); | |
| 33850 | ||
| 33851 | union_obj.requires_comptime = .wip; | |
| 33852 | for (union_obj.fields.values()) |field| { | |
| 33853 | if (try sema.typeRequiresComptime(field.ty)) { | |
| 33854 | union_obj.requires_comptime = .yes; | |
| 33855 | return true; | |
| 33856 | } | |
| 33857 | } | |
| 33858 | union_obj.requires_comptime = .no; | |
| 33859 | return false; | |
| 33860 | }, | |
| 33861 | } | |
| 33862 | }, | |
| 33863 | ||
| 33841 | 33864 | .opaque_type => false, |
| 33842 | 33865 | |
| 33843 | 33866 | // values, not types |
| 33867 | .un => unreachable, | |
| 33844 | 33868 | .simple_value => unreachable, |
| 33845 | 33869 | .extern_func => unreachable, |
| 33846 | 33870 | .int => unreachable, |
| ... | ... | @@ -33905,8 +33929,9 @@ fn unionFieldIndex( |
| 33905 | 33929 | field_name: []const u8, |
| 33906 | 33930 | field_src: LazySrcLoc, |
| 33907 | 33931 | ) !u32 { |
| 33932 | const mod = sema.mod; | |
| 33908 | 33933 | const union_ty = try sema.resolveTypeFields(unresolved_union_ty); |
| 33909 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 33934 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 33910 | 33935 | const field_index_usize = union_obj.fields.getIndex(field_name) orelse |
| 33911 | 33936 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 33912 | 33937 | return @intCast(u32, field_index_usize); |
src/TypedValue.zig+2-2| ... | ... | @@ -91,7 +91,7 @@ pub fn print( |
| 91 | 91 | try writer.writeAll(".{ "); |
| 92 | 92 | |
| 93 | 93 | try print(.{ |
| 94 | .ty = ty.cast(Type.Payload.Union).?.data.tag_ty, | |
| 94 | .ty = mod.unionPtr(mod.intern_pool.indexToKey(ty.ip_index).union_type.index).tag_ty, | |
| 95 | 95 | .val = union_val.tag, |
| 96 | 96 | }, writer, level - 1, mod); |
| 97 | 97 | try writer.writeAll(" = "); |
| ... | ... | @@ -185,7 +185,7 @@ pub fn print( |
| 185 | 185 | }, |
| 186 | 186 | } |
| 187 | 187 | } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) { |
| 188 | const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index]; | |
| 188 | const field_name = field_ptr.container_ty.unionFields(mod).keys()[field_ptr.field_index]; | |
| 189 | 189 | return writer.print(".{s}", .{field_name}); |
| 190 | 190 | } else if (field_ptr.container_ty.isSlice(mod)) { |
| 191 | 191 | switch (field_ptr.field_index) { |
src/arch/aarch64/abi.zig+2-2| ... | ... | @@ -79,7 +79,7 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 { |
| 79 | 79 | const invalid = std.math.maxInt(u8); |
| 80 | 80 | switch (ty.zigTypeTag(mod)) { |
| 81 | 81 | .Union => { |
| 82 | const fields = ty.unionFields(); | |
| 82 | const fields = ty.unionFields(mod); | |
| 83 | 83 | var max_count: u8 = 0; |
| 84 | 84 | for (fields.values()) |field| { |
| 85 | 85 | const field_count = countFloats(field.ty, mod, maybe_float_bits); |
| ... | ... | @@ -118,7 +118,7 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 { |
| 118 | 118 | pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type { |
| 119 | 119 | switch (ty.zigTypeTag(mod)) { |
| 120 | 120 | .Union => { |
| 121 | const fields = ty.unionFields(); | |
| 121 | const fields = ty.unionFields(mod); | |
| 122 | 122 | for (fields.values()) |field| { |
| 123 | 123 | if (getFloatArrayType(field.ty, mod)) |some| return some; |
| 124 | 124 | } |
src/arch/arm/abi.zig+2-2| ... | ... | @@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { |
| 62 | 62 | const float_count = countFloats(ty, mod, &maybe_float_bits); |
| 63 | 63 | if (float_count <= byval_float_count) return .byval; |
| 64 | 64 | |
| 65 | for (ty.unionFields().values()) |field| { | |
| 65 | for (ty.unionFields(mod).values()) |field| { | |
| 66 | 66 | if (field.ty.bitSize(mod) > 32 or field.normalAlignment(mod) > 32) { |
| 67 | 67 | return Class.arrSize(bit_size, 64); |
| 68 | 68 | } |
| ... | ... | @@ -121,7 +121,7 @@ fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 { |
| 121 | 121 | const invalid = std.math.maxInt(u32); |
| 122 | 122 | switch (ty.zigTypeTag(mod)) { |
| 123 | 123 | .Union => { |
| 124 | const fields = ty.unionFields(); | |
| 124 | const fields = ty.unionFields(mod); | |
| 125 | 125 | var max_count: u32 = 0; |
| 126 | 126 | for (fields.values()) |field| { |
| 127 | 127 | const field_count = countFloats(field.ty, mod, maybe_float_bits); |
src/arch/wasm/CodeGen.zig+5-5| ... | ... | @@ -1739,8 +1739,8 @@ fn isByRef(ty: Type, mod: *Module) bool { |
| 1739 | 1739 | .Frame, |
| 1740 | 1740 | => return ty.hasRuntimeBitsIgnoreComptime(mod), |
| 1741 | 1741 | .Union => { |
| 1742 | if (ty.castTag(.@"union")) |union_ty| { | |
| 1743 | if (union_ty.data.layout == .Packed) { | |
| 1742 | if (mod.typeToUnion(ty)) |union_obj| { | |
| 1743 | if (union_obj.layout == .Packed) { | |
| 1744 | 1744 | return ty.abiSize(mod) > 8; |
| 1745 | 1745 | } |
| 1746 | 1746 | } |
| ... | ... | @@ -3175,7 +3175,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3175 | 3175 | }, |
| 3176 | 3176 | .Union => { |
| 3177 | 3177 | // in this case we have a packed union which will not be passed by reference. |
| 3178 | const union_ty = ty.cast(Type.Payload.Union).?.data; | |
| 3178 | const union_ty = mod.typeToUnion(ty).?; | |
| 3179 | 3179 | const union_obj = val.castTag(.@"union").?.data; |
| 3180 | 3180 | const field_index = ty.unionTagFieldIndex(union_obj.tag, func.bin_file.base.options.module.?).?; |
| 3181 | 3181 | const field_ty = union_ty.fields.values()[field_index].ty; |
| ... | ... | @@ -5086,12 +5086,12 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5086 | 5086 | const result = result: { |
| 5087 | 5087 | const union_ty = func.typeOfIndex(inst); |
| 5088 | 5088 | const layout = union_ty.unionGetLayout(mod); |
| 5089 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 5089 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 5090 | 5090 | const field = union_obj.fields.values()[extra.field_index]; |
| 5091 | 5091 | const field_name = union_obj.fields.keys()[extra.field_index]; |
| 5092 | 5092 | |
| 5093 | 5093 | const tag_int = blk: { |
| 5094 | const tag_ty = union_ty.unionTagTypeHypothetical(); | |
| 5094 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); | |
| 5095 | 5095 | const enum_field_index = tag_ty.enumFieldIndex(field_name).?; |
| 5096 | 5096 | var tag_val_payload: Value.Payload.U32 = .{ |
| 5097 | 5097 | .base = .{ .tag = .enum_field_index }, |
src/arch/wasm/abi.zig+5-5| ... | ... | @@ -70,8 +70,8 @@ pub fn classifyType(ty: Type, mod: *Module) [2]Class { |
| 70 | 70 | } |
| 71 | 71 | const layout = ty.unionGetLayout(mod); |
| 72 | 72 | std.debug.assert(layout.tag_size == 0); |
| 73 | if (ty.unionFields().count() > 1) return memory; | |
| 74 | return classifyType(ty.unionFields().values()[0].ty, mod); | |
| 73 | if (ty.unionFields(mod).count() > 1) return memory; | |
| 74 | return classifyType(ty.unionFields(mod).values()[0].ty, mod); | |
| 75 | 75 | }, |
| 76 | 76 | .ErrorUnion, |
| 77 | 77 | .Frame, |
| ... | ... | @@ -111,11 +111,11 @@ pub fn scalarType(ty: Type, mod: *Module) Type { |
| 111 | 111 | if (ty.containerLayout(mod) != .Packed) { |
| 112 | 112 | const layout = ty.unionGetLayout(mod); |
| 113 | 113 | if (layout.payload_size == 0 and layout.tag_size != 0) { |
| 114 | return scalarType(ty.unionTagTypeSafety().?, mod); | |
| 114 | return scalarType(ty.unionTagTypeSafety(mod).?, mod); | |
| 115 | 115 | } |
| 116 | std.debug.assert(ty.unionFields().count() == 1); | |
| 116 | std.debug.assert(ty.unionFields(mod).count() == 1); | |
| 117 | 117 | } |
| 118 | return scalarType(ty.unionFields().values()[0].ty, mod); | |
| 118 | return scalarType(ty.unionFields(mod).values()[0].ty, mod); | |
| 119 | 119 | }, |
| 120 | 120 | else => return ty, |
| 121 | 121 | } |
src/arch/x86_64/CodeGen.zig+2-2| ... | ... | @@ -11410,9 +11410,9 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11410 | 11410 | |
| 11411 | 11411 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 11412 | 11412 | |
| 11413 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 11413 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 11414 | 11414 | const field_name = union_obj.fields.keys()[extra.field_index]; |
| 11415 | const tag_ty = union_ty.unionTagTypeSafety().?; | |
| 11415 | const tag_ty = union_obj.tag_ty; | |
| 11416 | 11416 | const field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?); |
| 11417 | 11417 | var tag_pl = Value.Payload.U32{ .base = .{ .tag = .enum_field_index }, .data = field_index }; |
| 11418 | 11418 | const tag_val = Value.initPayload(&tag_pl.base); |
src/arch/x86_64/abi.zig+1-1| ... | ... | @@ -338,7 +338,7 @@ pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { |
| 338 | 338 | if (ty_size > 64) |
| 339 | 339 | return memory_class; |
| 340 | 340 | |
| 341 | const fields = ty.unionFields(); | |
| 341 | const fields = ty.unionFields(mod); | |
| 342 | 342 | for (fields.values()) |field| { |
| 343 | 343 | if (field.abi_align != 0) { |
| 344 | 344 | if (field.abi_align < field.ty.abiAlignment(mod)) { |
src/codegen.zig+3-3| ... | ... | @@ -568,7 +568,7 @@ pub fn generateSymbol( |
| 568 | 568 | |
| 569 | 569 | if (layout.payload_size == 0) { |
| 570 | 570 | return generateSymbol(bin_file, src_loc, .{ |
| 571 | .ty = typed_value.ty.unionTagType().?, | |
| 571 | .ty = typed_value.ty.unionTagType(mod).?, | |
| 572 | 572 | .val = union_obj.tag, |
| 573 | 573 | }, code, debug_output, reloc_info); |
| 574 | 574 | } |
| ... | ... | @@ -576,7 +576,7 @@ pub fn generateSymbol( |
| 576 | 576 | // Check if we should store the tag first. |
| 577 | 577 | if (layout.tag_align >= layout.payload_align) { |
| 578 | 578 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 579 | .ty = typed_value.ty.unionTagType().?, | |
| 579 | .ty = typed_value.ty.unionTagType(mod).?, | |
| 580 | 580 | .val = union_obj.tag, |
| 581 | 581 | }, code, debug_output, reloc_info)) { |
| 582 | 582 | .ok => {}, |
| ... | ... | @@ -584,7 +584,7 @@ pub fn generateSymbol( |
| 584 | 584 | } |
| 585 | 585 | } |
| 586 | 586 | |
| 587 | const union_ty = typed_value.ty.cast(Type.Payload.Union).?.data; | |
| 587 | const union_ty = mod.typeToUnion(typed_value.ty).?; | |
| 588 | 588 | const field_index = typed_value.ty.unionTagFieldIndex(union_obj.tag, mod).?; |
| 589 | 589 | assert(union_ty.haveFieldTypes()); |
| 590 | 590 | const field_ty = union_ty.fields.values()[field_index].ty; |
src/codegen/c.zig+49-45| ... | ... | @@ -853,7 +853,7 @@ pub const DeclGen = struct { |
| 853 | 853 | } |
| 854 | 854 | |
| 855 | 855 | try writer.writeByte('{'); |
| 856 | if (ty.unionTagTypeSafety()) |tag_ty| { | |
| 856 | if (ty.unionTagTypeSafety(mod)) |tag_ty| { | |
| 857 | 857 | const layout = ty.unionGetLayout(mod); |
| 858 | 858 | if (layout.tag_size != 0) { |
| 859 | 859 | try writer.writeAll(" .tag = "); |
| ... | ... | @@ -863,12 +863,12 @@ pub const DeclGen = struct { |
| 863 | 863 | if (layout.tag_size != 0) try writer.writeByte(','); |
| 864 | 864 | try writer.writeAll(" .payload = {"); |
| 865 | 865 | } |
| 866 | for (ty.unionFields().values()) |field| { | |
| 866 | for (ty.unionFields(mod).values()) |field| { | |
| 867 | 867 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 868 | 868 | try dg.renderValue(writer, field.ty, val, initializer_type); |
| 869 | 869 | break; |
| 870 | 870 | } |
| 871 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); | |
| 871 | if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}'); | |
| 872 | 872 | return writer.writeByte('}'); |
| 873 | 873 | }, |
| 874 | 874 | .ErrorUnion => { |
| ... | ... | @@ -1451,8 +1451,8 @@ pub const DeclGen = struct { |
| 1451 | 1451 | } |
| 1452 | 1452 | |
| 1453 | 1453 | const field_i = ty.unionTagFieldIndex(union_obj.tag, mod).?; |
| 1454 | const field_ty = ty.unionFields().values()[field_i].ty; | |
| 1455 | const field_name = ty.unionFields().keys()[field_i]; | |
| 1454 | const field_ty = ty.unionFields(mod).values()[field_i].ty; | |
| 1455 | const field_name = ty.unionFields(mod).keys()[field_i]; | |
| 1456 | 1456 | if (ty.containerLayout(mod) == .Packed) { |
| 1457 | 1457 | if (field_ty.hasRuntimeBits(mod)) { |
| 1458 | 1458 | if (field_ty.isPtrAtRuntime(mod)) { |
| ... | ... | @@ -1472,7 +1472,7 @@ pub const DeclGen = struct { |
| 1472 | 1472 | } |
| 1473 | 1473 | |
| 1474 | 1474 | try writer.writeByte('{'); |
| 1475 | if (ty.unionTagTypeSafety()) |tag_ty| { | |
| 1475 | if (ty.unionTagTypeSafety(mod)) |tag_ty| { | |
| 1476 | 1476 | const layout = ty.unionGetLayout(mod); |
| 1477 | 1477 | if (layout.tag_size != 0) { |
| 1478 | 1478 | try writer.writeAll(" .tag = "); |
| ... | ... | @@ -1486,12 +1486,12 @@ pub const DeclGen = struct { |
| 1486 | 1486 | try writer.print(" .{ } = ", .{fmtIdent(field_name)}); |
| 1487 | 1487 | try dg.renderValue(writer, field_ty, union_obj.val, initializer_type); |
| 1488 | 1488 | try writer.writeByte(' '); |
| 1489 | } else for (ty.unionFields().values()) |field| { | |
| 1489 | } else for (ty.unionFields(mod).values()) |field| { | |
| 1490 | 1490 | if (!field.ty.hasRuntimeBits(mod)) continue; |
| 1491 | 1491 | try dg.renderValue(writer, field.ty, Value.undef, initializer_type); |
| 1492 | 1492 | break; |
| 1493 | 1493 | } |
| 1494 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); | |
| 1494 | if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}'); | |
| 1495 | 1495 | try writer.writeByte('}'); |
| 1496 | 1496 | }, |
| 1497 | 1497 | |
| ... | ... | @@ -5238,13 +5238,13 @@ fn fieldLocation( |
| 5238 | 5238 | .Auto, .Extern => { |
| 5239 | 5239 | const field_ty = container_ty.structFieldType(field_index, mod); |
| 5240 | 5240 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 5241 | return if (container_ty.unionTagTypeSafety() != null and | |
| 5241 | return if (container_ty.unionTagTypeSafety(mod) != null and | |
| 5242 | 5242 | !container_ty.unionHasAllZeroBitFieldTypes(mod)) |
| 5243 | 5243 | .{ .field = .{ .identifier = "payload" } } |
| 5244 | 5244 | else |
| 5245 | 5245 | .begin; |
| 5246 | const field_name = container_ty.unionFields().keys()[field_index]; | |
| 5247 | return .{ .field = if (container_ty.unionTagTypeSafety()) |_| | |
| 5246 | const field_name = container_ty.unionFields(mod).keys()[field_index]; | |
| 5247 | return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_| | |
| 5248 | 5248 | .{ .payload_identifier = field_name } |
| 5249 | 5249 | else |
| 5250 | 5250 | .{ .identifier = field_name } }; |
| ... | ... | @@ -5424,37 +5424,6 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5424 | 5424 | else |
| 5425 | 5425 | .{ .identifier = struct_ty.structFieldName(extra.field_index, mod) }, |
| 5426 | 5426 | |
| 5427 | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout(mod) == .Packed) { | |
| 5428 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5429 | const operand_local = try f.allocLocal(inst, struct_ty); | |
| 5430 | try f.writeCValue(writer, operand_local, .Other); | |
| 5431 | try writer.writeAll(" = "); | |
| 5432 | try f.writeCValue(writer, struct_byval, .Initializer); | |
| 5433 | try writer.writeAll(";\n"); | |
| 5434 | break :blk operand_local; | |
| 5435 | } else struct_byval; | |
| 5436 | ||
| 5437 | const local = try f.allocLocal(inst, inst_ty); | |
| 5438 | try writer.writeAll("memcpy(&"); | |
| 5439 | try f.writeCValue(writer, local, .Other); | |
| 5440 | try writer.writeAll(", &"); | |
| 5441 | try f.writeCValue(writer, operand_lval, .Other); | |
| 5442 | try writer.writeAll(", sizeof("); | |
| 5443 | try f.renderType(writer, inst_ty); | |
| 5444 | try writer.writeAll("));\n"); | |
| 5445 | ||
| 5446 | if (struct_byval == .constant) { | |
| 5447 | try freeLocal(f, inst, operand_lval.new_local, 0); | |
| 5448 | } | |
| 5449 | ||
| 5450 | return local; | |
| 5451 | } else field_name: { | |
| 5452 | const name = struct_ty.unionFields().keys()[extra.field_index]; | |
| 5453 | break :field_name if (struct_ty.unionTagTypeSafety()) |_| | |
| 5454 | .{ .payload_identifier = name } | |
| 5455 | else | |
| 5456 | .{ .identifier = name }; | |
| 5457 | }, | |
| 5458 | 5427 | else => unreachable, |
| 5459 | 5428 | }, |
| 5460 | 5429 | else => switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) { |
| ... | ... | @@ -5520,6 +5489,41 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5520 | 5489 | return local; |
| 5521 | 5490 | }, |
| 5522 | 5491 | }, |
| 5492 | .union_type => |union_type| field_name: { | |
| 5493 | const union_obj = mod.unionPtr(union_type.index); | |
| 5494 | if (union_obj.layout == .Packed) { | |
| 5495 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5496 | const operand_local = try f.allocLocal(inst, struct_ty); | |
| 5497 | try f.writeCValue(writer, operand_local, .Other); | |
| 5498 | try writer.writeAll(" = "); | |
| 5499 | try f.writeCValue(writer, struct_byval, .Initializer); | |
| 5500 | try writer.writeAll(";\n"); | |
| 5501 | break :blk operand_local; | |
| 5502 | } else struct_byval; | |
| 5503 | ||
| 5504 | const local = try f.allocLocal(inst, inst_ty); | |
| 5505 | try writer.writeAll("memcpy(&"); | |
| 5506 | try f.writeCValue(writer, local, .Other); | |
| 5507 | try writer.writeAll(", &"); | |
| 5508 | try f.writeCValue(writer, operand_lval, .Other); | |
| 5509 | try writer.writeAll(", sizeof("); | |
| 5510 | try f.renderType(writer, inst_ty); | |
| 5511 | try writer.writeAll("));\n"); | |
| 5512 | ||
| 5513 | if (struct_byval == .constant) { | |
| 5514 | try freeLocal(f, inst, operand_lval.new_local, 0); | |
| 5515 | } | |
| 5516 | ||
| 5517 | return local; | |
| 5518 | } else { | |
| 5519 | const name = union_obj.fields.keys()[extra.field_index]; | |
| 5520 | break :field_name if (union_type.hasTag()) .{ | |
| 5521 | .payload_identifier = name, | |
| 5522 | } else .{ | |
| 5523 | .identifier = name, | |
| 5524 | }; | |
| 5525 | } | |
| 5526 | }, | |
| 5523 | 5527 | else => unreachable, |
| 5524 | 5528 | }, |
| 5525 | 5529 | }; |
| ... | ... | @@ -6461,7 +6465,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6461 | 6465 | const union_ty = f.typeOf(bin_op.lhs).childType(mod); |
| 6462 | 6466 | const layout = union_ty.unionGetLayout(mod); |
| 6463 | 6467 | if (layout.tag_size == 0) return .none; |
| 6464 | const tag_ty = union_ty.unionTagTypeSafety().?; | |
| 6468 | const tag_ty = union_ty.unionTagTypeSafety(mod).?; | |
| 6465 | 6469 | |
| 6466 | 6470 | const writer = f.object.writer(); |
| 6467 | 6471 | const a = try Assignment.start(f, writer, tag_ty); |
| ... | ... | @@ -6907,7 +6911,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6907 | 6911 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 6908 | 6912 | |
| 6909 | 6913 | const union_ty = f.typeOfIndex(inst); |
| 6910 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 6914 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 6911 | 6915 | const field_name = union_obj.fields.keys()[extra.field_index]; |
| 6912 | 6916 | const payload_ty = f.typeOf(extra.init); |
| 6913 | 6917 | const payload = try f.resolveInst(extra.init); |
| ... | ... | @@ -6923,7 +6927,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6923 | 6927 | return local; |
| 6924 | 6928 | } |
| 6925 | 6929 | |
| 6926 | const field: CValue = if (union_ty.unionTagTypeSafety()) |tag_ty| field: { | |
| 6930 | const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: { | |
| 6927 | 6931 | const layout = union_ty.unionGetLayout(mod); |
| 6928 | 6932 | if (layout.tag_size != 0) { |
| 6929 | 6933 | const field_index = tag_ty.enumFieldIndex(field_name).?; |
src/codegen/c/type.zig+13-13| ... | ... | @@ -303,7 +303,7 @@ pub const CType = extern union { |
| 303 | 303 | ); |
| 304 | 304 | } |
| 305 | 305 | pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs { |
| 306 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 306 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 307 | 307 | const union_payload_align = union_obj.abiAlignment(mod, false); |
| 308 | 308 | return init(union_payload_align, union_payload_align); |
| 309 | 309 | } |
| ... | ... | @@ -1498,7 +1498,7 @@ pub const CType = extern union { |
| 1498 | 1498 | if (lookup.isMutable()) { |
| 1499 | 1499 | for (0..switch (zig_ty_tag) { |
| 1500 | 1500 | .Struct => ty.structFieldCount(mod), |
| 1501 | .Union => ty.unionFields().count(), | |
| 1501 | .Union => ty.unionFields(mod).count(), | |
| 1502 | 1502 | else => unreachable, |
| 1503 | 1503 | }) |field_i| { |
| 1504 | 1504 | const field_ty = ty.structFieldType(field_i, mod); |
| ... | ... | @@ -1531,7 +1531,7 @@ pub const CType = extern union { |
| 1531 | 1531 | .payload => unreachable, |
| 1532 | 1532 | }); |
| 1533 | 1533 | } else { |
| 1534 | const tag_ty = ty.unionTagTypeSafety(); | |
| 1534 | const tag_ty = ty.unionTagTypeSafety(mod); | |
| 1535 | 1535 | const is_tagged_union_wrapper = kind != .payload and tag_ty != null; |
| 1536 | 1536 | const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper; |
| 1537 | 1537 | switch (kind) { |
| ... | ... | @@ -1580,7 +1580,7 @@ pub const CType = extern union { |
| 1580 | 1580 | var is_packed = false; |
| 1581 | 1581 | for (0..switch (zig_ty_tag) { |
| 1582 | 1582 | .Struct => ty.structFieldCount(mod), |
| 1583 | .Union => ty.unionFields().count(), | |
| 1583 | .Union => ty.unionFields(mod).count(), | |
| 1584 | 1584 | else => unreachable, |
| 1585 | 1585 | }) |field_i| { |
| 1586 | 1586 | const field_ty = ty.structFieldType(field_i, mod); |
| ... | ... | @@ -1930,7 +1930,7 @@ pub const CType = extern union { |
| 1930 | 1930 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 1931 | 1931 | const fields_len = switch (zig_ty_tag) { |
| 1932 | 1932 | .Struct => ty.structFieldCount(mod), |
| 1933 | .Union => ty.unionFields().count(), | |
| 1933 | .Union => ty.unionFields(mod).count(), | |
| 1934 | 1934 | else => unreachable, |
| 1935 | 1935 | }; |
| 1936 | 1936 | |
| ... | ... | @@ -1956,7 +1956,7 @@ pub const CType = extern union { |
| 1956 | 1956 | else |
| 1957 | 1957 | arena.dupeZ(u8, switch (zig_ty_tag) { |
| 1958 | 1958 | .Struct => ty.structFieldName(field_i, mod), |
| 1959 | .Union => ty.unionFields().keys()[field_i], | |
| 1959 | .Union => ty.unionFields(mod).keys()[field_i], | |
| 1960 | 1960 | else => unreachable, |
| 1961 | 1961 | }), |
| 1962 | 1962 | .type = store.set.typeToIndex(field_ty, mod, switch (kind) { |
| ... | ... | @@ -1986,7 +1986,7 @@ pub const CType = extern union { |
| 1986 | 1986 | unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{ |
| 1987 | 1987 | .fields = fields_pl, |
| 1988 | 1988 | .owner_decl = ty.getOwnerDecl(mod), |
| 1989 | .id = if (ty.unionTagTypeSafety()) |_| 0 else unreachable, | |
| 1989 | .id = if (ty.unionTagTypeSafety(mod)) |_| 0 else unreachable, | |
| 1990 | 1990 | } }; |
| 1991 | 1991 | return initPayload(unnamed_pl); |
| 1992 | 1992 | }, |
| ... | ... | @@ -2085,7 +2085,7 @@ pub const CType = extern union { |
| 2085 | 2085 | var c_field_i: usize = 0; |
| 2086 | 2086 | for (0..switch (zig_ty_tag) { |
| 2087 | 2087 | .Struct => ty.structFieldCount(mod), |
| 2088 | .Union => ty.unionFields().count(), | |
| 2088 | .Union => ty.unionFields(mod).count(), | |
| 2089 | 2089 | else => unreachable, |
| 2090 | 2090 | }) |field_i| { |
| 2091 | 2091 | const field_ty = ty.structFieldType(field_i, mod); |
| ... | ... | @@ -2106,7 +2106,7 @@ pub const CType = extern union { |
| 2106 | 2106 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2107 | 2107 | else switch (zig_ty_tag) { |
| 2108 | 2108 | .Struct => ty.structFieldName(field_i, mod), |
| 2109 | .Union => ty.unionFields().keys()[field_i], | |
| 2109 | .Union => ty.unionFields(mod).keys()[field_i], | |
| 2110 | 2110 | else => unreachable, |
| 2111 | 2111 | }, |
| 2112 | 2112 | mem.span(c_field.name), |
| ... | ... | @@ -2122,7 +2122,7 @@ pub const CType = extern union { |
| 2122 | 2122 | .packed_unnamed_union, |
| 2123 | 2123 | => switch (self.kind) { |
| 2124 | 2124 | .forward, .forward_parameter, .complete, .parameter, .global => unreachable, |
| 2125 | .payload => if (ty.unionTagTypeSafety()) |_| { | |
| 2125 | .payload => if (ty.unionTagTypeSafety(mod)) |_| { | |
| 2126 | 2126 | const data = cty.cast(Payload.Unnamed).?.data; |
| 2127 | 2127 | return ty.getOwnerDecl(mod) == data.owner_decl and data.id == 0; |
| 2128 | 2128 | } else unreachable, |
| ... | ... | @@ -2211,7 +2211,7 @@ pub const CType = extern union { |
| 2211 | 2211 | const zig_ty_tag = ty.zigTypeTag(mod); |
| 2212 | 2212 | for (0..switch (ty.zigTypeTag(mod)) { |
| 2213 | 2213 | .Struct => ty.structFieldCount(mod), |
| 2214 | .Union => ty.unionFields().count(), | |
| 2214 | .Union => ty.unionFields(mod).count(), | |
| 2215 | 2215 | else => unreachable, |
| 2216 | 2216 | }) |field_i| { |
| 2217 | 2217 | const field_ty = ty.structFieldType(field_i, mod); |
| ... | ... | @@ -2228,7 +2228,7 @@ pub const CType = extern union { |
| 2228 | 2228 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable |
| 2229 | 2229 | else switch (zig_ty_tag) { |
| 2230 | 2230 | .Struct => ty.structFieldName(field_i, mod), |
| 2231 | .Union => ty.unionFields().keys()[field_i], | |
| 2231 | .Union => ty.unionFields(mod).keys()[field_i], | |
| 2232 | 2232 | else => unreachable, |
| 2233 | 2233 | }); |
| 2234 | 2234 | autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align"); |
| ... | ... | @@ -2241,7 +2241,7 @@ pub const CType = extern union { |
| 2241 | 2241 | .packed_unnamed_union, |
| 2242 | 2242 | => switch (self.kind) { |
| 2243 | 2243 | .forward, .forward_parameter, .complete, .parameter, .global => unreachable, |
| 2244 | .payload => if (ty.unionTagTypeSafety()) |_| { | |
| 2244 | .payload => if (ty.unionTagTypeSafety(mod)) |_| { | |
| 2245 | 2245 | autoHash(hasher, ty.getOwnerDecl(mod)); |
| 2246 | 2246 | autoHash(hasher, @as(u32, 0)); |
| 2247 | 2247 | } else unreachable, |
src/codegen/llvm.zig+7-7| ... | ... | @@ -2178,7 +2178,7 @@ pub const Object = struct { |
| 2178 | 2178 | break :blk fwd_decl; |
| 2179 | 2179 | }; |
| 2180 | 2180 | |
| 2181 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 2181 | const union_obj = mod.typeToUnion(ty).?; | |
| 2182 | 2182 | if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2183 | 2183 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); |
| 2184 | 2184 | dib.replaceTemporary(fwd_decl, union_di_ty); |
| ... | ... | @@ -3063,7 +3063,7 @@ pub const DeclGen = struct { |
| 3063 | 3063 | gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator()); |
| 3064 | 3064 | |
| 3065 | 3065 | const layout = t.unionGetLayout(mod); |
| 3066 | const union_obj = t.cast(Type.Payload.Union).?.data; | |
| 3066 | const union_obj = mod.typeToUnion(t).?; | |
| 3067 | 3067 | |
| 3068 | 3068 | if (union_obj.layout == .Packed) { |
| 3069 | 3069 | const bitsize = @intCast(c_uint, t.bitSize(mod)); |
| ... | ... | @@ -3797,11 +3797,11 @@ pub const DeclGen = struct { |
| 3797 | 3797 | |
| 3798 | 3798 | if (layout.payload_size == 0) { |
| 3799 | 3799 | return lowerValue(dg, .{ |
| 3800 | .ty = tv.ty.unionTagTypeSafety().?, | |
| 3800 | .ty = tv.ty.unionTagTypeSafety(mod).?, | |
| 3801 | 3801 | .val = tag_and_val.tag, |
| 3802 | 3802 | }); |
| 3803 | 3803 | } |
| 3804 | const union_obj = tv.ty.cast(Type.Payload.Union).?.data; | |
| 3804 | const union_obj = mod.typeToUnion(tv.ty).?; | |
| 3805 | 3805 | const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?; |
| 3806 | 3806 | assert(union_obj.haveFieldTypes()); |
| 3807 | 3807 | |
| ... | ... | @@ -3851,7 +3851,7 @@ pub const DeclGen = struct { |
| 3851 | 3851 | } |
| 3852 | 3852 | } |
| 3853 | 3853 | const llvm_tag_value = try lowerValue(dg, .{ |
| 3854 | .ty = tv.ty.unionTagTypeSafety().?, | |
| 3854 | .ty = tv.ty.unionTagTypeSafety(mod).?, | |
| 3855 | 3855 | .val = tag_and_val.tag, |
| 3856 | 3856 | }); |
| 3857 | 3857 | var fields: [3]*llvm.Value = undefined; |
| ... | ... | @@ -9410,7 +9410,7 @@ pub const FuncGen = struct { |
| 9410 | 9410 | const union_ty = self.typeOfIndex(inst); |
| 9411 | 9411 | const union_llvm_ty = try self.dg.lowerType(union_ty); |
| 9412 | 9412 | const layout = union_ty.unionGetLayout(mod); |
| 9413 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 9413 | const union_obj = mod.typeToUnion(union_ty).?; | |
| 9414 | 9414 | |
| 9415 | 9415 | if (union_obj.layout == .Packed) { |
| 9416 | 9416 | const big_bits = union_ty.bitSize(mod); |
| ... | ... | @@ -9427,7 +9427,7 @@ pub const FuncGen = struct { |
| 9427 | 9427 | } |
| 9428 | 9428 | |
| 9429 | 9429 | const tag_int = blk: { |
| 9430 | const tag_ty = union_ty.unionTagTypeHypothetical(); | |
| 9430 | const tag_ty = union_ty.unionTagTypeHypothetical(mod); | |
| 9431 | 9431 | const union_field_name = union_obj.fields.keys()[extra.field_index]; |
| 9432 | 9432 | const enum_field_index = tag_ty.enumFieldIndex(union_field_name).?; |
| 9433 | 9433 | var tag_val_payload: Value.Payload.U32 = .{ |
src/codegen/spirv.zig+5-5| ... | ... | @@ -755,10 +755,10 @@ pub const DeclGen = struct { |
| 755 | 755 | const layout = ty.unionGetLayout(mod); |
| 756 | 756 | |
| 757 | 757 | if (layout.payload_size == 0) { |
| 758 | return try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag); | |
| 758 | return try self.lower(ty.unionTagTypeSafety(mod).?, tag_and_val.tag); | |
| 759 | 759 | } |
| 760 | 760 | |
| 761 | const union_ty = ty.cast(Type.Payload.Union).?.data; | |
| 761 | const union_ty = mod.typeToUnion(ty).?; | |
| 762 | 762 | if (union_ty.layout == .Packed) { |
| 763 | 763 | return dg.todo("packed union constants", .{}); |
| 764 | 764 | } |
| ... | ... | @@ -770,7 +770,7 @@ pub const DeclGen = struct { |
| 770 | 770 | const tag_first = layout.tag_align >= layout.payload_align; |
| 771 | 771 | |
| 772 | 772 | if (has_tag and tag_first) { |
| 773 | try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag); | |
| 773 | try self.lower(ty.unionTagTypeSafety(mod).?, tag_and_val.tag); | |
| 774 | 774 | } |
| 775 | 775 | |
| 776 | 776 | const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: { |
| ... | ... | @@ -782,7 +782,7 @@ pub const DeclGen = struct { |
| 782 | 782 | try self.addUndef(payload_padding_len); |
| 783 | 783 | |
| 784 | 784 | if (has_tag and !tag_first) { |
| 785 | try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag); | |
| 785 | try self.lower(ty.unionTagTypeSafety(mod).?, tag_and_val.tag); | |
| 786 | 786 | } |
| 787 | 787 | |
| 788 | 788 | try self.addUndef(layout.padding); |
| ... | ... | @@ -1121,7 +1121,7 @@ pub const DeclGen = struct { |
| 1121 | 1121 | fn resolveUnionType(self: *DeclGen, ty: Type, maybe_active_field: ?usize) !CacheRef { |
| 1122 | 1122 | const mod = self.module; |
| 1123 | 1123 | const layout = ty.unionGetLayout(mod); |
| 1124 | const union_ty = ty.cast(Type.Payload.Union).?.data; | |
| 1124 | const union_ty = mod.typeToUnion(ty).?; | |
| 1125 | 1125 | |
| 1126 | 1126 | if (union_ty.layout == .Packed) { |
| 1127 | 1127 | return self.todo("packed union types", .{}); |
src/link/Dwarf.zig+2-2| ... | ... | @@ -432,7 +432,7 @@ pub const DeclState = struct { |
| 432 | 432 | }, |
| 433 | 433 | .Union => { |
| 434 | 434 | const layout = ty.unionGetLayout(mod); |
| 435 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 435 | const union_obj = mod.typeToUnion(ty).?; | |
| 436 | 436 | const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0; |
| 437 | 437 | const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size; |
| 438 | 438 | const is_tagged = layout.tag_size > 0; |
| ... | ... | @@ -476,7 +476,7 @@ pub const DeclState = struct { |
| 476 | 476 | try dbg_info_buffer.writer().print("{s}\x00", .{union_name}); |
| 477 | 477 | } |
| 478 | 478 | |
| 479 | const fields = ty.unionFields(); | |
| 479 | const fields = ty.unionFields(mod); | |
| 480 | 480 | for (fields.keys()) |field_name| { |
| 481 | 481 | const field = fields.get(field_name).?; |
| 482 | 482 | if (!field.ty.hasRuntimeBits(mod)) continue; |
src/type.zig+176-223| ... | ... | @@ -68,11 +68,6 @@ pub const Type = struct { |
| 68 | 68 | .enum_simple, |
| 69 | 69 | .enum_numbered, |
| 70 | 70 | => return .Enum, |
| 71 | ||
| 72 | .@"union", | |
| 73 | .union_safety_tagged, | |
| 74 | .union_tagged, | |
| 75 | => return .Union, | |
| 76 | 71 | }, |
| 77 | 72 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 78 | 73 | .int_type => return .Int, |
| ... | ... | @@ -140,6 +135,7 @@ pub const Type = struct { |
| 140 | 135 | }, |
| 141 | 136 | |
| 142 | 137 | // values, not types |
| 138 | .un => unreachable, | |
| 143 | 139 | .extern_func => unreachable, |
| 144 | 140 | .int => unreachable, |
| 145 | 141 | .ptr => unreachable, |
| ... | ... | @@ -585,12 +581,6 @@ pub const Type = struct { |
| 585 | 581 | const b_enum_obj = (b.cast(Payload.EnumNumbered) orelse return false).data; |
| 586 | 582 | return a_enum_obj == b_enum_obj; |
| 587 | 583 | }, |
| 588 | ||
| 589 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 590 | const a_union_obj = a.cast(Payload.Union).?.data; | |
| 591 | const b_union_obj = (b.cast(Payload.Union) orelse return false).data; | |
| 592 | return a_union_obj == b_union_obj; | |
| 593 | }, | |
| 594 | 584 | } |
| 595 | 585 | } |
| 596 | 586 | |
| ... | ... | @@ -752,12 +742,6 @@ pub const Type = struct { |
| 752 | 742 | std.hash.autoHash(hasher, std.builtin.TypeId.Enum); |
| 753 | 743 | std.hash.autoHash(hasher, enum_obj); |
| 754 | 744 | }, |
| 755 | ||
| 756 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 757 | const union_obj: *const Module.Union = ty.cast(Payload.Union).?.data; | |
| 758 | std.hash.autoHash(hasher, std.builtin.TypeId.Union); | |
| 759 | std.hash.autoHash(hasher, union_obj); | |
| 760 | }, | |
| 761 | 745 | } |
| 762 | 746 | } |
| 763 | 747 | |
| ... | ... | @@ -935,7 +919,6 @@ pub const Type = struct { |
| 935 | 919 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), |
| 936 | 920 | .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred), |
| 937 | 921 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), |
| 938 | .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union), | |
| 939 | 922 | .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple), |
| 940 | 923 | .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered), |
| 941 | 924 | .enum_full, .enum_nonexhaustive => return self.copyPayloadShallow(allocator, Payload.EnumFull), |
| ... | ... | @@ -1011,12 +994,6 @@ pub const Type = struct { |
| 1011 | 994 | while (true) { |
| 1012 | 995 | const t = ty.tag(); |
| 1013 | 996 | switch (t) { |
| 1014 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 1015 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 1016 | return writer.print("({s} decl={d})", .{ | |
| 1017 | @tagName(t), union_obj.owner_decl, | |
| 1018 | }); | |
| 1019 | }, | |
| 1020 | 997 | .enum_full, .enum_nonexhaustive => { |
| 1021 | 998 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| 1022 | 999 | return writer.print("({s} decl={d})", .{ |
| ... | ... | @@ -1221,11 +1198,6 @@ pub const Type = struct { |
| 1221 | 1198 | .inferred_alloc_const => unreachable, |
| 1222 | 1199 | .inferred_alloc_mut => unreachable, |
| 1223 | 1200 | |
| 1224 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 1225 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 1226 | const decl = mod.declPtr(union_obj.owner_decl); | |
| 1227 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1228 | }, | |
| 1229 | 1201 | .enum_full, .enum_nonexhaustive => { |
| 1230 | 1202 | const enum_full = ty.cast(Payload.EnumFull).?.data; |
| 1231 | 1203 | const decl = mod.declPtr(enum_full.owner_decl); |
| ... | ... | @@ -1518,13 +1490,18 @@ pub const Type = struct { |
| 1518 | 1490 | } |
| 1519 | 1491 | }, |
| 1520 | 1492 | |
| 1521 | .union_type => @panic("TODO"), | |
| 1493 | .union_type => |union_type| { | |
| 1494 | const union_obj = mod.unionPtr(union_type.index); | |
| 1495 | const decl = mod.declPtr(union_obj.owner_decl); | |
| 1496 | try decl.renderFullyQualifiedName(mod, writer); | |
| 1497 | }, | |
| 1522 | 1498 | .opaque_type => |opaque_type| { |
| 1523 | 1499 | const decl = mod.declPtr(opaque_type.decl); |
| 1524 | 1500 | try decl.renderFullyQualifiedName(mod, writer); |
| 1525 | 1501 | }, |
| 1526 | 1502 | |
| 1527 | 1503 | // values, not types |
| 1504 | .un => unreachable, | |
| 1528 | 1505 | .simple_value => unreachable, |
| 1529 | 1506 | .extern_func => unreachable, |
| 1530 | 1507 | .int => unreachable, |
| ... | ... | @@ -1627,45 +1604,6 @@ pub const Type = struct { |
| 1627 | 1604 | return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); |
| 1628 | 1605 | }, |
| 1629 | 1606 | |
| 1630 | .@"union" => { | |
| 1631 | const union_obj = ty.castTag(.@"union").?.data; | |
| 1632 | if (union_obj.status == .field_types_wip) { | |
| 1633 | // In this case, we guess that hasRuntimeBits() for this type is true, | |
| 1634 | // and then later if our guess was incorrect, we emit a compile error. | |
| 1635 | union_obj.assumed_runtime_bits = true; | |
| 1636 | return true; | |
| 1637 | } | |
| 1638 | switch (strat) { | |
| 1639 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | |
| 1640 | .eager => assert(union_obj.haveFieldTypes()), | |
| 1641 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, | |
| 1642 | } | |
| 1643 | for (union_obj.fields.values()) |value| { | |
| 1644 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | |
| 1645 | return true; | |
| 1646 | } else { | |
| 1647 | return false; | |
| 1648 | } | |
| 1649 | }, | |
| 1650 | .union_safety_tagged, .union_tagged => { | |
| 1651 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 1652 | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) { | |
| 1653 | return true; | |
| 1654 | } | |
| 1655 | ||
| 1656 | switch (strat) { | |
| 1657 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | |
| 1658 | .eager => assert(union_obj.haveFieldTypes()), | |
| 1659 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, | |
| 1660 | } | |
| 1661 | for (union_obj.fields.values()) |value| { | |
| 1662 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | |
| 1663 | return true; | |
| 1664 | } else { | |
| 1665 | return false; | |
| 1666 | } | |
| 1667 | }, | |
| 1668 | ||
| 1669 | 1607 | .array => return ty.arrayLen(mod) != 0 and |
| 1670 | 1608 | try ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), |
| 1671 | 1609 | .array_sentinel => return ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), |
| ... | ... | @@ -1795,10 +1733,40 @@ pub const Type = struct { |
| 1795 | 1733 | } |
| 1796 | 1734 | }, |
| 1797 | 1735 | |
| 1798 | .union_type => @panic("TODO"), | |
| 1736 | .union_type => |union_type| { | |
| 1737 | const union_obj = mod.unionPtr(union_type.index); | |
| 1738 | switch (union_type.runtime_tag) { | |
| 1739 | .none => { | |
| 1740 | if (union_obj.status == .field_types_wip) { | |
| 1741 | // In this case, we guess that hasRuntimeBits() for this type is true, | |
| 1742 | // and then later if our guess was incorrect, we emit a compile error. | |
| 1743 | union_obj.assumed_runtime_bits = true; | |
| 1744 | return true; | |
| 1745 | } | |
| 1746 | }, | |
| 1747 | .safety, .tagged => { | |
| 1748 | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) { | |
| 1749 | return true; | |
| 1750 | } | |
| 1751 | }, | |
| 1752 | } | |
| 1753 | switch (strat) { | |
| 1754 | .sema => |sema| _ = try sema.resolveTypeFields(ty), | |
| 1755 | .eager => assert(union_obj.haveFieldTypes()), | |
| 1756 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, | |
| 1757 | } | |
| 1758 | for (union_obj.fields.values()) |value| { | |
| 1759 | if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) | |
| 1760 | return true; | |
| 1761 | } else { | |
| 1762 | return false; | |
| 1763 | } | |
| 1764 | }, | |
| 1765 | ||
| 1799 | 1766 | .opaque_type => true, |
| 1800 | 1767 | |
| 1801 | 1768 | // values, not types |
| 1769 | .un => unreachable, | |
| 1802 | 1770 | .simple_value => unreachable, |
| 1803 | 1771 | .extern_func => unreachable, |
| 1804 | 1772 | .int => unreachable, |
| ... | ... | @@ -1847,8 +1815,6 @@ pub const Type = struct { |
| 1847 | 1815 | => ty.childType(mod).hasWellDefinedLayout(mod), |
| 1848 | 1816 | |
| 1849 | 1817 | .optional => ty.isPtrLikeOptional(mod), |
| 1850 | .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto, | |
| 1851 | .union_tagged => false, | |
| 1852 | 1818 | }, |
| 1853 | 1819 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 1854 | 1820 | .int_type => true, |
| ... | ... | @@ -1912,10 +1878,14 @@ pub const Type = struct { |
| 1912 | 1878 | }; |
| 1913 | 1879 | return struct_obj.layout != .Auto; |
| 1914 | 1880 | }, |
| 1915 | .union_type => @panic("TODO"), | |
| 1881 | .union_type => |union_type| switch (union_type.runtime_tag) { | |
| 1882 | .none, .safety => mod.unionPtr(union_type.index).layout != .Auto, | |
| 1883 | .tagged => false, | |
| 1884 | }, | |
| 1916 | 1885 | .opaque_type => false, |
| 1917 | 1886 | |
| 1918 | 1887 | // values, not types |
| 1888 | .un => unreachable, | |
| 1919 | 1889 | .simple_value => unreachable, |
| 1920 | 1890 | .extern_func => unreachable, |
| 1921 | 1891 | .int => unreachable, |
| ... | ... | @@ -2146,14 +2116,6 @@ pub const Type = struct { |
| 2146 | 2116 | const int_tag_ty = try ty.intTagType(mod); |
| 2147 | 2117 | return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) }; |
| 2148 | 2118 | }, |
| 2149 | .@"union" => { | |
| 2150 | const union_obj = ty.castTag(.@"union").?.data; | |
| 2151 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, false); | |
| 2152 | }, | |
| 2153 | .union_safety_tagged, .union_tagged => { | |
| 2154 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 2155 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true); | |
| 2156 | }, | |
| 2157 | 2119 | |
| 2158 | 2120 | .inferred_alloc_const, |
| 2159 | 2121 | .inferred_alloc_mut, |
| ... | ... | @@ -2312,10 +2274,14 @@ pub const Type = struct { |
| 2312 | 2274 | } |
| 2313 | 2275 | return AbiAlignmentAdvanced{ .scalar = big_align }; |
| 2314 | 2276 | }, |
| 2315 | .union_type => @panic("TODO"), | |
| 2277 | .union_type => |union_type| { | |
| 2278 | const union_obj = mod.unionPtr(union_type.index); | |
| 2279 | return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag()); | |
| 2280 | }, | |
| 2316 | 2281 | .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 }, |
| 2317 | 2282 | |
| 2318 | 2283 | // values, not types |
| 2284 | .un => unreachable, | |
| 2319 | 2285 | .simple_value => unreachable, |
| 2320 | 2286 | .extern_func => unreachable, |
| 2321 | 2287 | .int => unreachable, |
| ... | ... | @@ -2508,14 +2474,6 @@ pub const Type = struct { |
| 2508 | 2474 | const int_tag_ty = try ty.intTagType(mod); |
| 2509 | 2475 | return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) }; |
| 2510 | 2476 | }, |
| 2511 | .@"union" => { | |
| 2512 | const union_obj = ty.castTag(.@"union").?.data; | |
| 2513 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, false); | |
| 2514 | }, | |
| 2515 | .union_safety_tagged, .union_tagged => { | |
| 2516 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 2517 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true); | |
| 2518 | }, | |
| 2519 | 2477 | |
| 2520 | 2478 | .array => { |
| 2521 | 2479 | const payload = ty.castTag(.array).?.data; |
| ... | ... | @@ -2737,10 +2695,14 @@ pub const Type = struct { |
| 2737 | 2695 | return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) }; |
| 2738 | 2696 | }, |
| 2739 | 2697 | }, |
| 2740 | .union_type => @panic("TODO"), | |
| 2698 | .union_type => |union_type| { | |
| 2699 | const union_obj = mod.unionPtr(union_type.index); | |
| 2700 | return abiSizeAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag()); | |
| 2701 | }, | |
| 2741 | 2702 | .opaque_type => unreachable, // no size available |
| 2742 | 2703 | |
| 2743 | 2704 | // values, not types |
| 2705 | .un => unreachable, | |
| 2744 | 2706 | .simple_value => unreachable, |
| 2745 | 2707 | .extern_func => unreachable, |
| 2746 | 2708 | .int => unreachable, |
| ... | ... | @@ -2860,21 +2822,6 @@ pub const Type = struct { |
| 2860 | 2822 | return try bitSizeAdvanced(int_tag_ty, mod, opt_sema); |
| 2861 | 2823 | }, |
| 2862 | 2824 | |
| 2863 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 2864 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | |
| 2865 | if (ty.containerLayout(mod) != .Packed) { | |
| 2866 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | |
| 2867 | } | |
| 2868 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 2869 | assert(union_obj.haveFieldTypes()); | |
| 2870 | ||
| 2871 | var size: u64 = 0; | |
| 2872 | for (union_obj.fields.values()) |field| { | |
| 2873 | size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema)); | |
| 2874 | } | |
| 2875 | return size; | |
| 2876 | }, | |
| 2877 | ||
| 2878 | 2825 | .array => { |
| 2879 | 2826 | const payload = ty.castTag(.array).?.data; |
| 2880 | 2827 | const elem_size = std.math.max(payload.elem_type.abiAlignment(mod), payload.elem_type.abiSize(mod)); |
| ... | ... | @@ -2996,10 +2943,24 @@ pub const Type = struct { |
| 2996 | 2943 | return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema); |
| 2997 | 2944 | }, |
| 2998 | 2945 | |
| 2999 | .union_type => @panic("TODO"), | |
| 2946 | .union_type => |union_type| { | |
| 2947 | if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty); | |
| 2948 | if (ty.containerLayout(mod) != .Packed) { | |
| 2949 | return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8; | |
| 2950 | } | |
| 2951 | const union_obj = mod.unionPtr(union_type.index); | |
| 2952 | assert(union_obj.haveFieldTypes()); | |
| 2953 | ||
| 2954 | var size: u64 = 0; | |
| 2955 | for (union_obj.fields.values()) |field| { | |
| 2956 | size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema)); | |
| 2957 | } | |
| 2958 | return size; | |
| 2959 | }, | |
| 3000 | 2960 | .opaque_type => unreachable, |
| 3001 | 2961 | |
| 3002 | 2962 | // values, not types |
| 2963 | .un => unreachable, | |
| 3003 | 2964 | .simple_value => unreachable, |
| 3004 | 2965 | .extern_func => unreachable, |
| 3005 | 2966 | .int => unreachable, |
| ... | ... | @@ -3022,8 +2983,8 @@ pub const Type = struct { |
| 3022 | 2983 | return true; |
| 3023 | 2984 | }, |
| 3024 | 2985 | .Union => { |
| 3025 | if (ty.cast(Payload.Union)) |union_ty| { | |
| 3026 | return union_ty.data.haveLayout(); | |
| 2986 | if (mod.typeToUnion(ty)) |union_obj| { | |
| 2987 | return union_obj.haveLayout(); | |
| 3027 | 2988 | } |
| 3028 | 2989 | return true; |
| 3029 | 2990 | }, |
| ... | ... | @@ -3413,76 +3374,71 @@ pub const Type = struct { |
| 3413 | 3374 | |
| 3414 | 3375 | /// Returns the tag type of a union, if the type is a union and it has a tag type. |
| 3415 | 3376 | /// Otherwise, returns `null`. |
| 3416 | pub fn unionTagType(ty: Type) ?Type { | |
| 3417 | return switch (ty.tag()) { | |
| 3418 | .union_tagged => { | |
| 3419 | const union_obj = ty.castTag(.union_tagged).?.data; | |
| 3420 | assert(union_obj.haveFieldTypes()); | |
| 3421 | return union_obj.tag_ty; | |
| 3377 | pub fn unionTagType(ty: Type, mod: *Module) ?Type { | |
| 3378 | return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 3379 | .union_type => |union_type| switch (union_type.runtime_tag) { | |
| 3380 | .tagged => { | |
| 3381 | const union_obj = mod.unionPtr(union_type.index); | |
| 3382 | assert(union_obj.haveFieldTypes()); | |
| 3383 | return union_obj.tag_ty; | |
| 3384 | }, | |
| 3385 | else => null, | |
| 3422 | 3386 | }, |
| 3423 | ||
| 3424 | 3387 | else => null, |
| 3425 | 3388 | }; |
| 3426 | 3389 | } |
| 3427 | 3390 | |
| 3428 | 3391 | /// Same as `unionTagType` but includes safety tag. |
| 3429 | 3392 | /// Codegen should use this version. |
| 3430 | pub fn unionTagTypeSafety(ty: Type) ?Type { | |
| 3431 | return switch (ty.tag()) { | |
| 3432 | .union_safety_tagged, .union_tagged => { | |
| 3433 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 3393 | pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type { | |
| 3394 | return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 3395 | .union_type => |union_type| { | |
| 3396 | if (!union_type.hasTag()) return null; | |
| 3397 | const union_obj = mod.unionPtr(union_type.index); | |
| 3434 | 3398 | assert(union_obj.haveFieldTypes()); |
| 3435 | 3399 | return union_obj.tag_ty; |
| 3436 | 3400 | }, |
| 3437 | ||
| 3438 | 3401 | else => null, |
| 3439 | 3402 | }; |
| 3440 | 3403 | } |
| 3441 | 3404 | |
| 3442 | 3405 | /// Asserts the type is a union; returns the tag type, even if the tag will |
| 3443 | 3406 | /// not be stored at runtime. |
| 3444 | pub fn unionTagTypeHypothetical(ty: Type) Type { | |
| 3445 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 3407 | pub fn unionTagTypeHypothetical(ty: Type, mod: *Module) Type { | |
| 3408 | const union_obj = mod.typeToUnion(ty).?; | |
| 3446 | 3409 | assert(union_obj.haveFieldTypes()); |
| 3447 | 3410 | return union_obj.tag_ty; |
| 3448 | 3411 | } |
| 3449 | 3412 | |
| 3450 | pub fn unionFields(ty: Type) Module.Union.Fields { | |
| 3451 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 3413 | pub fn unionFields(ty: Type, mod: *Module) Module.Union.Fields { | |
| 3414 | const union_obj = mod.typeToUnion(ty).?; | |
| 3452 | 3415 | assert(union_obj.haveFieldTypes()); |
| 3453 | 3416 | return union_obj.fields; |
| 3454 | 3417 | } |
| 3455 | 3418 | |
| 3456 | 3419 | pub fn unionFieldType(ty: Type, enum_tag: Value, mod: *Module) Type { |
| 3457 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 3420 | const union_obj = mod.typeToUnion(ty).?; | |
| 3458 | 3421 | const index = ty.unionTagFieldIndex(enum_tag, mod).?; |
| 3459 | 3422 | assert(union_obj.haveFieldTypes()); |
| 3460 | 3423 | return union_obj.fields.values()[index].ty; |
| 3461 | 3424 | } |
| 3462 | 3425 | |
| 3463 | 3426 | pub fn unionTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?usize { |
| 3464 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 3427 | const union_obj = mod.typeToUnion(ty).?; | |
| 3465 | 3428 | const index = union_obj.tag_ty.enumTagFieldIndex(enum_tag, mod) orelse return null; |
| 3466 | 3429 | const name = union_obj.tag_ty.enumFieldName(index); |
| 3467 | 3430 | return union_obj.fields.getIndex(name); |
| 3468 | 3431 | } |
| 3469 | 3432 | |
| 3470 | 3433 | pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *Module) bool { |
| 3471 | return ty.cast(Payload.Union).?.data.hasAllZeroBitFieldTypes(mod); | |
| 3434 | const union_obj = mod.typeToUnion(ty).?; | |
| 3435 | return union_obj.hasAllZeroBitFieldTypes(mod); | |
| 3472 | 3436 | } |
| 3473 | 3437 | |
| 3474 | 3438 | pub fn unionGetLayout(ty: Type, mod: *Module) Module.Union.Layout { |
| 3475 | switch (ty.tag()) { | |
| 3476 | .@"union" => { | |
| 3477 | const union_obj = ty.castTag(.@"union").?.data; | |
| 3478 | return union_obj.getLayout(mod, false); | |
| 3479 | }, | |
| 3480 | .union_safety_tagged, .union_tagged => { | |
| 3481 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 3482 | return union_obj.getLayout(mod, true); | |
| 3483 | }, | |
| 3484 | else => unreachable, | |
| 3485 | } | |
| 3439 | const union_type = mod.intern_pool.indexToKey(ty.ip_index).union_type; | |
| 3440 | const union_obj = mod.unionPtr(union_type.index); | |
| 3441 | return union_obj.getLayout(mod, union_type.hasTag()); | |
| 3486 | 3442 | } |
| 3487 | 3443 | |
| 3488 | 3444 | pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout { |
| ... | ... | @@ -3490,9 +3446,6 @@ pub const Type = struct { |
| 3490 | 3446 | .empty_struct_type => .Auto, |
| 3491 | 3447 | .none => switch (ty.tag()) { |
| 3492 | 3448 | .tuple, .anon_struct => .Auto, |
| 3493 | .@"union" => ty.castTag(.@"union").?.data.layout, | |
| 3494 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout, | |
| 3495 | .union_tagged => ty.castTag(.union_tagged).?.data.layout, | |
| 3496 | 3449 | else => unreachable, |
| 3497 | 3450 | }, |
| 3498 | 3451 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| ... | ... | @@ -3500,6 +3453,10 @@ pub const Type = struct { |
| 3500 | 3453 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto; |
| 3501 | 3454 | return struct_obj.layout; |
| 3502 | 3455 | }, |
| 3456 | .union_type => |union_type| { | |
| 3457 | const union_obj = mod.unionPtr(union_type.index); | |
| 3458 | return union_obj.layout; | |
| 3459 | }, | |
| 3503 | 3460 | else => unreachable, |
| 3504 | 3461 | }, |
| 3505 | 3462 | }; |
| ... | ... | @@ -3777,6 +3734,7 @@ pub const Type = struct { |
| 3777 | 3734 | .opaque_type => unreachable, |
| 3778 | 3735 | |
| 3779 | 3736 | // values, not types |
| 3737 | .un => unreachable, | |
| 3780 | 3738 | .simple_value => unreachable, |
| 3781 | 3739 | .extern_func => unreachable, |
| 3782 | 3740 | .int => unreachable, |
| ... | ... | @@ -4038,16 +3996,6 @@ pub const Type = struct { |
| 4038 | 3996 | return null; |
| 4039 | 3997 | } |
| 4040 | 3998 | }, |
| 4041 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 4042 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4043 | const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null; | |
| 4044 | if (union_obj.fields.count() == 0) return Value.@"unreachable"; | |
| 4045 | const only_field = union_obj.fields.values()[0]; | |
| 4046 | const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null; | |
| 4047 | _ = tag_val; | |
| 4048 | _ = val_val; | |
| 4049 | return Value.empty_struct; | |
| 4050 | }, | |
| 4051 | 3999 | |
| 4052 | 4000 | .array => { |
| 4053 | 4001 | if (ty.arrayLen(mod) == 0) |
| ... | ... | @@ -4153,10 +4101,23 @@ pub const Type = struct { |
| 4153 | 4101 | return empty.toValue(); |
| 4154 | 4102 | }, |
| 4155 | 4103 | |
| 4156 | .union_type => @panic("TODO"), | |
| 4104 | .union_type => |union_type| { | |
| 4105 | const union_obj = mod.unionPtr(union_type.index); | |
| 4106 | const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null; | |
| 4107 | if (union_obj.fields.count() == 0) return Value.@"unreachable"; | |
| 4108 | const only_field = union_obj.fields.values()[0]; | |
| 4109 | const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null; | |
| 4110 | const only = try mod.intern(.{ .un = .{ | |
| 4111 | .ty = ty.ip_index, | |
| 4112 | .tag = tag_val.ip_index, | |
| 4113 | .val = val_val.ip_index, | |
| 4114 | } }); | |
| 4115 | return only.toValue(); | |
| 4116 | }, | |
| 4157 | 4117 | .opaque_type => return null, |
| 4158 | 4118 | |
| 4159 | 4119 | // values, not types |
| 4120 | .un => unreachable, | |
| 4160 | 4121 | .simple_value => unreachable, |
| 4161 | 4122 | .extern_func => unreachable, |
| 4162 | 4123 | .int => unreachable, |
| ... | ... | @@ -4216,20 +4177,6 @@ pub const Type = struct { |
| 4216 | 4177 | return false; |
| 4217 | 4178 | }, |
| 4218 | 4179 | |
| 4219 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 4220 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 4221 | switch (union_obj.requires_comptime) { | |
| 4222 | .wip, .unknown => { | |
| 4223 | // Return false to avoid incorrect dependency loops. | |
| 4224 | // This will be handled correctly once merged with | |
| 4225 | // `Sema.typeRequiresComptime`. | |
| 4226 | return false; | |
| 4227 | }, | |
| 4228 | .no => return false, | |
| 4229 | .yes => return true, | |
| 4230 | } | |
| 4231 | }, | |
| 4232 | ||
| 4233 | 4180 | .error_union => return ty.errorUnionPayload().comptimeOnly(mod), |
| 4234 | 4181 | .anyframe_T => { |
| 4235 | 4182 | const child_ty = ty.castTag(.anyframe_T).?.data; |
| ... | ... | @@ -4321,10 +4268,24 @@ pub const Type = struct { |
| 4321 | 4268 | } |
| 4322 | 4269 | }, |
| 4323 | 4270 | |
| 4324 | .union_type => @panic("TODO"), | |
| 4271 | .union_type => |union_type| { | |
| 4272 | const union_obj = mod.unionPtr(union_type.index); | |
| 4273 | switch (union_obj.requires_comptime) { | |
| 4274 | .wip, .unknown => { | |
| 4275 | // Return false to avoid incorrect dependency loops. | |
| 4276 | // This will be handled correctly once merged with | |
| 4277 | // `Sema.typeRequiresComptime`. | |
| 4278 | return false; | |
| 4279 | }, | |
| 4280 | .no => return false, | |
| 4281 | .yes => return true, | |
| 4282 | } | |
| 4283 | }, | |
| 4284 | ||
| 4325 | 4285 | .opaque_type => false, |
| 4326 | 4286 | |
| 4327 | 4287 | // values, not types |
| 4288 | .un => unreachable, | |
| 4328 | 4289 | .simple_value => unreachable, |
| 4329 | 4290 | .extern_func => unreachable, |
| 4330 | 4291 | .int => unreachable, |
| ... | ... | @@ -4378,15 +4339,13 @@ pub const Type = struct { |
| 4378 | 4339 | .none => switch (ty.tag()) { |
| 4379 | 4340 | .enum_full => ty.castTag(.enum_full).?.data.namespace.toOptional(), |
| 4380 | 4341 | .enum_nonexhaustive => ty.castTag(.enum_nonexhaustive).?.data.namespace.toOptional(), |
| 4381 | .@"union" => ty.castTag(.@"union").?.data.namespace.toOptional(), | |
| 4382 | .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.namespace.toOptional(), | |
| 4383 | .union_tagged => ty.castTag(.union_tagged).?.data.namespace.toOptional(), | |
| 4384 | ||
| 4385 | 4342 | else => .none, |
| 4386 | 4343 | }, |
| 4387 | 4344 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 4388 | 4345 | .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), |
| 4389 | 4346 | .struct_type => |struct_type| struct_type.namespace, |
| 4347 | .union_type => |union_type| mod.unionPtr(union_type.index).namespace.toOptional(), | |
| 4348 | ||
| 4390 | 4349 | else => .none, |
| 4391 | 4350 | }, |
| 4392 | 4351 | }; |
| ... | ... | @@ -4474,20 +4433,23 @@ pub const Type = struct { |
| 4474 | 4433 | |
| 4475 | 4434 | /// Asserts the type is an enum or a union. |
| 4476 | 4435 | pub fn intTagType(ty: Type, mod: *Module) !Type { |
| 4477 | switch (ty.tag()) { | |
| 4478 | .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty, | |
| 4479 | .enum_numbered => return ty.castTag(.enum_numbered).?.data.tag_ty, | |
| 4480 | .enum_simple => { | |
| 4481 | const enum_simple = ty.castTag(.enum_simple).?.data; | |
| 4482 | const field_count = enum_simple.fields.count(); | |
| 4483 | const bits: u16 = if (field_count == 0) 0 else std.math.log2_int_ceil(usize, field_count); | |
| 4484 | return mod.intType(.unsigned, bits); | |
| 4436 | return switch (ty.ip_index) { | |
| 4437 | .none => switch (ty.tag()) { | |
| 4438 | .enum_full, .enum_nonexhaustive => ty.cast(Payload.EnumFull).?.data.tag_ty, | |
| 4439 | .enum_numbered => ty.castTag(.enum_numbered).?.data.tag_ty, | |
| 4440 | .enum_simple => { | |
| 4441 | const enum_simple = ty.castTag(.enum_simple).?.data; | |
| 4442 | const field_count = enum_simple.fields.count(); | |
| 4443 | const bits: u16 = if (field_count == 0) 0 else std.math.log2_int_ceil(usize, field_count); | |
| 4444 | return mod.intType(.unsigned, bits); | |
| 4445 | }, | |
| 4446 | else => unreachable, | |
| 4485 | 4447 | }, |
| 4486 | .union_tagged => { | |
| 4487 | return ty.castTag(.union_tagged).?.data.tag_ty.intTagType(mod); | |
| 4448 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 4449 | .union_type => |union_type| mod.unionPtr(union_type.index).tag_ty.intTagType(mod), | |
| 4450 | else => unreachable, | |
| 4488 | 4451 | }, |
| 4489 | else => unreachable, | |
| 4490 | } | |
| 4452 | }; | |
| 4491 | 4453 | } |
| 4492 | 4454 | |
| 4493 | 4455 | pub fn isNonexhaustiveEnum(ty: Type) bool { |
| ... | ... | @@ -4663,10 +4625,6 @@ pub const Type = struct { |
| 4663 | 4625 | pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type { |
| 4664 | 4626 | return switch (ty.ip_index) { |
| 4665 | 4627 | .none => switch (ty.tag()) { |
| 4666 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 4667 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4668 | return union_obj.fields.values()[index].ty; | |
| 4669 | }, | |
| 4670 | 4628 | .tuple => return ty.castTag(.tuple).?.data.types[index], |
| 4671 | 4629 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index], |
| 4672 | 4630 | else => unreachable, |
| ... | ... | @@ -4676,6 +4634,10 @@ pub const Type = struct { |
| 4676 | 4634 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 4677 | 4635 | return struct_obj.fields.values()[index].ty; |
| 4678 | 4636 | }, |
| 4637 | .union_type => |union_type| { | |
| 4638 | const union_obj = mod.unionPtr(union_type.index); | |
| 4639 | return union_obj.fields.values()[index].ty; | |
| 4640 | }, | |
| 4679 | 4641 | else => unreachable, |
| 4680 | 4642 | }, |
| 4681 | 4643 | }; |
| ... | ... | @@ -4684,10 +4646,6 @@ pub const Type = struct { |
| 4684 | 4646 | pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 { |
| 4685 | 4647 | switch (ty.ip_index) { |
| 4686 | 4648 | .none => switch (ty.tag()) { |
| 4687 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 4688 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4689 | return union_obj.fields.values()[index].normalAlignment(mod); | |
| 4690 | }, | |
| 4691 | 4649 | .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(mod), |
| 4692 | 4650 | .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(mod), |
| 4693 | 4651 | else => unreachable, |
| ... | ... | @@ -4698,6 +4656,10 @@ pub const Type = struct { |
| 4698 | 4656 | assert(struct_obj.layout != .Packed); |
| 4699 | 4657 | return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout); |
| 4700 | 4658 | }, |
| 4659 | .union_type => |union_type| { | |
| 4660 | const union_obj = mod.unionPtr(union_type.index); | |
| 4661 | return union_obj.fields.values()[index].normalAlignment(mod); | |
| 4662 | }, | |
| 4701 | 4663 | else => unreachable, |
| 4702 | 4664 | }, |
| 4703 | 4665 | } |
| ... | ... | @@ -4889,18 +4851,6 @@ pub const Type = struct { |
| 4889 | 4851 | return offset; |
| 4890 | 4852 | }, |
| 4891 | 4853 | |
| 4892 | .@"union" => return 0, | |
| 4893 | .union_safety_tagged, .union_tagged => { | |
| 4894 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4895 | const layout = union_obj.getLayout(mod, true); | |
| 4896 | if (layout.tag_align >= layout.payload_align) { | |
| 4897 | // {Tag, Payload} | |
| 4898 | return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align); | |
| 4899 | } else { | |
| 4900 | // {Payload, Tag} | |
| 4901 | return 0; | |
| 4902 | } | |
| 4903 | }, | |
| 4904 | 4854 | else => unreachable, |
| 4905 | 4855 | }, |
| 4906 | 4856 | else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| ... | ... | @@ -4917,6 +4867,20 @@ pub const Type = struct { |
| 4917 | 4867 | return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1)); |
| 4918 | 4868 | }, |
| 4919 | 4869 | |
| 4870 | .union_type => |union_type| { | |
| 4871 | if (!union_type.hasTag()) | |
| 4872 | return 0; | |
| 4873 | const union_obj = mod.unionPtr(union_type.index); | |
| 4874 | const layout = union_obj.getLayout(mod, true); | |
| 4875 | if (layout.tag_align >= layout.payload_align) { | |
| 4876 | // {Tag, Payload} | |
| 4877 | return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align); | |
| 4878 | } else { | |
| 4879 | // {Payload, Tag} | |
| 4880 | return 0; | |
| 4881 | } | |
| 4882 | }, | |
| 4883 | ||
| 4920 | 4884 | else => unreachable, |
| 4921 | 4885 | }, |
| 4922 | 4886 | } |
| ... | ... | @@ -4946,10 +4910,6 @@ pub const Type = struct { |
| 4946 | 4910 | const error_set = ty.castTag(.error_set).?.data; |
| 4947 | 4911 | return error_set.srcLoc(mod); |
| 4948 | 4912 | }, |
| 4949 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 4950 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4951 | return union_obj.srcLoc(mod); | |
| 4952 | }, | |
| 4953 | 4913 | |
| 4954 | 4914 | else => return null, |
| 4955 | 4915 | }, |
| ... | ... | @@ -4958,7 +4918,10 @@ pub const Type = struct { |
| 4958 | 4918 | const struct_obj = mod.structPtrUnwrap(struct_type.index).?; |
| 4959 | 4919 | return struct_obj.srcLoc(mod); |
| 4960 | 4920 | }, |
| 4961 | .union_type => @panic("TODO"), | |
| 4921 | .union_type => |union_type| { | |
| 4922 | const union_obj = mod.unionPtr(union_type.index); | |
| 4923 | return union_obj.srcLoc(mod); | |
| 4924 | }, | |
| 4962 | 4925 | .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type), |
| 4963 | 4926 | else => null, |
| 4964 | 4927 | }, |
| ... | ... | @@ -4985,10 +4948,6 @@ pub const Type = struct { |
| 4985 | 4948 | const error_set = ty.castTag(.error_set).?.data; |
| 4986 | 4949 | return error_set.owner_decl; |
| 4987 | 4950 | }, |
| 4988 | .@"union", .union_safety_tagged, .union_tagged => { | |
| 4989 | const union_obj = ty.cast(Payload.Union).?.data; | |
| 4990 | return union_obj.owner_decl; | |
| 4991 | }, | |
| 4992 | 4951 | |
| 4993 | 4952 | else => return null, |
| 4994 | 4953 | }, |
| ... | ... | @@ -4997,7 +4956,10 @@ pub const Type = struct { |
| 4997 | 4956 | const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return null; |
| 4998 | 4957 | return struct_obj.owner_decl; |
| 4999 | 4958 | }, |
| 5000 | .union_type => @panic("TODO"), | |
| 4959 | .union_type => |union_type| { | |
| 4960 | const union_obj = mod.unionPtr(union_type.index); | |
| 4961 | return union_obj.owner_decl; | |
| 4962 | }, | |
| 5001 | 4963 | .opaque_type => |opaque_type| opaque_type.decl, |
| 5002 | 4964 | else => null, |
| 5003 | 4965 | }, |
| ... | ... | @@ -5039,9 +5001,6 @@ pub const Type = struct { |
| 5039 | 5001 | /// The type is the inferred error set of a specific function. |
| 5040 | 5002 | error_set_inferred, |
| 5041 | 5003 | error_set_merged, |
| 5042 | @"union", | |
| 5043 | union_safety_tagged, | |
| 5044 | union_tagged, | |
| 5045 | 5004 | enum_simple, |
| 5046 | 5005 | enum_numbered, |
| 5047 | 5006 | enum_full, |
| ... | ... | @@ -5070,7 +5029,6 @@ pub const Type = struct { |
| 5070 | 5029 | .function => Payload.Function, |
| 5071 | 5030 | .error_union => Payload.ErrorUnion, |
| 5072 | 5031 | .error_set_single => Payload.Name, |
| 5073 | .@"union", .union_safety_tagged, .union_tagged => Payload.Union, | |
| 5074 | 5032 | .enum_full, .enum_nonexhaustive => Payload.EnumFull, |
| 5075 | 5033 | .enum_simple => Payload.EnumSimple, |
| 5076 | 5034 | .enum_numbered => Payload.EnumNumbered, |
| ... | ... | @@ -5373,11 +5331,6 @@ pub const Type = struct { |
| 5373 | 5331 | }; |
| 5374 | 5332 | }; |
| 5375 | 5333 | |
| 5376 | pub const Union = struct { | |
| 5377 | base: Payload, | |
| 5378 | data: *Module.Union, | |
| 5379 | }; | |
| 5380 | ||
| 5381 | 5334 | pub const EnumFull = struct { |
| 5382 | 5335 | base: Payload, |
| 5383 | 5336 | data: *Module.EnumFull, |
src/value.zig+6-6| ... | ... | @@ -715,7 +715,7 @@ pub const Value = struct { |
| 715 | 715 | } |
| 716 | 716 | |
| 717 | 717 | pub fn tagName(val: Value, ty: Type, mod: *Module) []const u8 { |
| 718 | if (ty.zigTypeTag(mod) == .Union) return val.unionTag().tagName(ty.unionTagTypeHypothetical(), mod); | |
| 718 | if (ty.zigTypeTag(mod) == .Union) return val.unionTag().tagName(ty.unionTagTypeHypothetical(mod), mod); | |
| 719 | 719 | |
| 720 | 720 | const field_index = switch (val.tag()) { |
| 721 | 721 | .enum_field_index => val.castTag(.enum_field_index).?.data, |
| ... | ... | @@ -1138,7 +1138,7 @@ pub const Value = struct { |
| 1138 | 1138 | .Extern => unreachable, // Handled in non-packed writeToMemory |
| 1139 | 1139 | .Packed => { |
| 1140 | 1140 | const field_index = ty.unionTagFieldIndex(val.unionTag(), mod); |
| 1141 | const field_type = ty.unionFields().values()[field_index.?].ty; | |
| 1141 | const field_type = ty.unionFields(mod).values()[field_index.?].ty; | |
| 1142 | 1142 | const field_val = try val.fieldValue(field_type, mod, field_index.?); |
| 1143 | 1143 | |
| 1144 | 1144 | return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset); |
| ... | ... | @@ -2021,7 +2021,7 @@ pub const Value = struct { |
| 2021 | 2021 | const b_union = b.castTag(.@"union").?.data; |
| 2022 | 2022 | switch (ty.containerLayout(mod)) { |
| 2023 | 2023 | .Packed, .Extern => { |
| 2024 | const tag_ty = ty.unionTagTypeHypothetical(); | |
| 2024 | const tag_ty = ty.unionTagTypeHypothetical(mod); | |
| 2025 | 2025 | if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) { |
| 2026 | 2026 | // In this case, we must disregard mismatching tags and compare |
| 2027 | 2027 | // based on the in-memory bytes of the payloads. |
| ... | ... | @@ -2029,7 +2029,7 @@ pub const Value = struct { |
| 2029 | 2029 | } |
| 2030 | 2030 | }, |
| 2031 | 2031 | .Auto => { |
| 2032 | const tag_ty = ty.unionTagTypeHypothetical(); | |
| 2032 | const tag_ty = ty.unionTagTypeHypothetical(mod); | |
| 2033 | 2033 | if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) { |
| 2034 | 2034 | return false; |
| 2035 | 2035 | } |
| ... | ... | @@ -2118,7 +2118,7 @@ pub const Value = struct { |
| 2118 | 2118 | return false; |
| 2119 | 2119 | } |
| 2120 | 2120 | const field_name = tuple.names[0]; |
| 2121 | const union_obj = ty.cast(Type.Payload.Union).?.data; | |
| 2121 | const union_obj = mod.typeToUnion(ty).?; | |
| 2122 | 2122 | const field_index = union_obj.fields.getIndex(field_name) orelse return false; |
| 2123 | 2123 | const tag_and_val = b.castTag(.@"union").?.data; |
| 2124 | 2124 | var field_tag_buf: Value.Payload.U32 = .{ |
| ... | ... | @@ -2297,7 +2297,7 @@ pub const Value = struct { |
| 2297 | 2297 | }, |
| 2298 | 2298 | .Union => { |
| 2299 | 2299 | const union_obj = val.cast(Payload.Union).?.data; |
| 2300 | if (ty.unionTagType()) |tag_ty| { | |
| 2300 | if (ty.unionTagType(mod)) |tag_ty| { | |
| 2301 | 2301 | union_obj.tag.hash(tag_ty, hasher, mod); |
| 2302 | 2302 | } |
| 2303 | 2303 | const active_field_ty = ty.unionFieldType(union_obj.tag, mod); |