| author | |
| committer | |
| log | f3dc53f6b53e8493b341f82cb06a56e33e80e6b7 |
| tree | a5c5c93af8ea6661214790e54e22fd5af3e0d6d6 |
| parent | 55e89255e18163bcc153138a4883ec8d85e0d517 |
* move inferred error sets into InternPool.
- they are now represented by pointing directly at the corresponding
function body value.
* inferred error set working memory is now in Sema and expires after
the Sema for the function corresponding to the inferred error set is
finished having its body analyzed.
* error sets use a InternPool.Index.Slice rather than an actual slice
to avoid lifetime issues.7 files changed, 1037 insertions(+), 739 deletions(-)
lib/std/array_hash_map.zig+6-4| ... | @@ -1669,8 +1669,9 @@ pub fn ArrayHashMapUnmanaged( | ... | @@ -1669,8 +1669,9 @@ pub fn ArrayHashMapUnmanaged( |
| 1669 | 1669 | ||
| 1670 | inline fn checkedHash(ctx: anytype, key: anytype) u32 { | 1670 | inline fn checkedHash(ctx: anytype, key: anytype) u32 { |
| 1671 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(key), K, u32, true); | 1671 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(key), K, u32, true); |
| 1672 | // If you get a compile error on the next line, it means that | 1672 | // If you get a compile error on the next line, it means that your |
| 1673 | const hash = ctx.hash(key); // your generic hash function doesn't accept your key | 1673 | // generic hash function doesn't accept your key. |
| 1674 | const hash = ctx.hash(key); | ||
| 1674 | if (@TypeOf(hash) != u32) { | 1675 | if (@TypeOf(hash) != u32) { |
| 1675 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++ | 1676 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++ |
| 1676 | @typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash))); | 1677 | @typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash))); |
| ... | @@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged( | ... | @@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged( |
| 1679 | } | 1680 | } |
| 1680 | inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool { | 1681 | inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool { |
| 1681 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(a), K, u32, true); | 1682 | comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(a), K, u32, true); |
| 1682 | // If you get a compile error on the next line, it means that | 1683 | // If you get a compile error on the next line, it means that your |
| 1683 | const eql = ctx.eql(a, b, b_index); // your generic eql function doesn't accept (self, adapt key, K, index) | 1684 | // generic eql function doesn't accept (self, adapt key, K, index). |
| 1685 | const eql = ctx.eql(a, b, b_index); | ||
| 1684 | if (@TypeOf(eql) != bool) { | 1686 | if (@TypeOf(eql) != bool) { |
| 1685 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++ | 1687 | @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++ |
| 1686 | @typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql))); | 1688 | @typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql))); |
src/InternPool.zig+510-204| ... | @@ -53,14 +53,6 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, | ... | @@ -53,14 +53,6 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, |
| 53 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. | 53 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. |
| 54 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, | 54 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, |
| 55 | 55 | ||
| 56 | /// InferredErrorSet objects are stored in this data structure because: | ||
| 57 | /// * They contain pointers such as the errors map and the set of other inferred error sets. | ||
| 58 | /// * They need to be mutated after creation. | ||
| 59 | allocated_inferred_error_sets: std.SegmentedList(Module.InferredErrorSet, 0) = .{}, | ||
| 60 | /// When a Struct object is freed from `allocated_inferred_error_sets`, it is | ||
| 61 | /// pushed into this stack. | ||
| 62 | inferred_error_sets_free_list: std.ArrayListUnmanaged(Module.InferredErrorSet.Index) = .{}, | ||
| 63 | |||
| 64 | /// Some types such as enums, structs, and unions need to store mappings from field names | 56 | /// Some types such as enums, structs, and unions need to store mappings from field names |
| 65 | /// to field index, or value to field index. In such cases, they will store the underlying | 57 | /// to field index, or value to field index. In such cases, they will store the underlying |
| 66 | /// field names and values directly, relying on one of these maps, stored separately, | 58 | /// field names and values directly, relying on one of these maps, stored separately, |
| ... | @@ -143,12 +135,24 @@ pub const NullTerminatedString = enum(u32) { | ... | @@ -143,12 +135,24 @@ pub const NullTerminatedString = enum(u32) { |
| 143 | empty = 0, | 135 | empty = 0, |
| 144 | _, | 136 | _, |
| 145 | 137 | ||
| 138 | /// An array of `NullTerminatedString` existing within the `extra` array. | ||
| 139 | /// This type exists to provide a struct with lifetime that is | ||
| 140 | /// not invalidated when items are added to the `InternPool`. | ||
| 141 | pub const Slice = struct { | ||
| 142 | start: u32, | ||
| 143 | len: u32, | ||
| 144 | |||
| 145 | pub fn get(slice: Slice, ip: *const InternPool) []NullTerminatedString { | ||
| 146 | return @ptrCast(ip.extra.items[slice.start..][0..slice.len]); | ||
| 147 | } | ||
| 148 | }; | ||
| 149 | |||
| 146 | pub fn toString(self: NullTerminatedString) String { | 150 | pub fn toString(self: NullTerminatedString) String { |
| 147 | return @as(String, @enumFromInt(@intFromEnum(self))); | 151 | return @enumFromInt(@intFromEnum(self)); |
| 148 | } | 152 | } |
| 149 | 153 | ||
| 150 | pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString { | 154 | pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString { |
| 151 | return @as(OptionalNullTerminatedString, @enumFromInt(@intFromEnum(self))); | 155 | return @enumFromInt(@intFromEnum(self)); |
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | const Adapter = struct { | 158 | const Adapter = struct { |
| ... | @@ -238,7 +242,8 @@ pub const Key = union(enum) { | ... | @@ -238,7 +242,8 @@ pub const Key = union(enum) { |
| 238 | enum_type: EnumType, | 242 | enum_type: EnumType, |
| 239 | func_type: FuncType, | 243 | func_type: FuncType, |
| 240 | error_set_type: ErrorSetType, | 244 | error_set_type: ErrorSetType, |
| 241 | inferred_error_set_type: Module.InferredErrorSet.Index, | 245 | /// The payload is the function body, either a `func_decl` or `func_instance`. |
| 246 | inferred_error_set_type: Index, | ||
| 242 | 247 | ||
| 243 | /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented | 248 | /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented |
| 244 | /// via `simple_value` and has a named `Index` tag for it. | 249 | /// via `simple_value` and has a named `Index` tag for it. |
| ... | @@ -287,14 +292,14 @@ pub const Key = union(enum) { | ... | @@ -287,14 +292,14 @@ pub const Key = union(enum) { |
| 287 | 292 | ||
| 288 | pub const ErrorSetType = struct { | 293 | pub const ErrorSetType = struct { |
| 289 | /// Set of error names, sorted by null terminated string index. | 294 | /// Set of error names, sorted by null terminated string index. |
| 290 | names: []const NullTerminatedString, | 295 | names: NullTerminatedString.Slice, |
| 291 | /// This is ignored by `get` but will always be provided by `indexToKey`. | 296 | /// This is ignored by `get` but will always be provided by `indexToKey`. |
| 292 | names_map: OptionalMapIndex = .none, | 297 | names_map: OptionalMapIndex = .none, |
| 293 | 298 | ||
| 294 | /// Look up field index based on field name. | 299 | /// Look up field index based on field name. |
| 295 | pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 { | 300 | pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 { |
| 296 | const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)]; | 301 | const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)]; |
| 297 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.names }; | 302 | const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) }; |
| 298 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; | 303 | const field_index = map.getIndexAdapted(name, adapter) orelse return null; |
| 299 | return @as(u32, @intCast(field_index)); | 304 | return @as(u32, @intCast(field_index)); |
| 300 | } | 305 | } |
| ... | @@ -565,6 +570,9 @@ pub const Key = union(enum) { | ... | @@ -565,6 +570,9 @@ pub const Key = union(enum) { |
| 565 | /// Index into extra array of the `zir_body_inst` corresponding to this function. | 570 | /// Index into extra array of the `zir_body_inst` corresponding to this function. |
| 566 | /// Used for mutating that data. | 571 | /// Used for mutating that data. |
| 567 | zir_body_inst_extra_index: u32, | 572 | zir_body_inst_extra_index: u32, |
| 573 | /// Index into extra array of the resolved inferred error set for this function. | ||
| 574 | /// Used for mutating that data. | ||
| 575 | resolved_error_set_extra_index: u32, | ||
| 568 | /// When a generic function is instantiated, branch_quota is inherited from the | 576 | /// When a generic function is instantiated, branch_quota is inherited from the |
| 569 | /// active Sema context. Importantly, this value is also updated when an existing | 577 | /// active Sema context. Importantly, this value is also updated when an existing |
| 570 | /// generic function instantiation is found and called. | 578 | /// generic function instantiation is found and called. |
| ... | @@ -603,13 +611,21 @@ pub const Key = union(enum) { | ... | @@ -603,13 +611,21 @@ pub const Key = union(enum) { |
| 603 | return @ptrCast(&ip.extra.items[func.analysis_extra_index]); | 611 | return @ptrCast(&ip.extra.items[func.analysis_extra_index]); |
| 604 | } | 612 | } |
| 605 | 613 | ||
| 614 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. | ||
| 606 | pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *Zir.Inst.Index { | 615 | pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *Zir.Inst.Index { |
| 607 | return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]); | 616 | return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]); |
| 608 | } | 617 | } |
| 609 | 618 | ||
| 619 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. | ||
| 610 | pub fn branchQuota(func: *const Func, ip: *const InternPool) *u32 { | 620 | pub fn branchQuota(func: *const Func, ip: *const InternPool) *u32 { |
| 611 | return &ip.extra.items[func.zir_body_inst_extra_index]; | 621 | return &ip.extra.items[func.zir_body_inst_extra_index]; |
| 612 | } | 622 | } |
| 623 | |||
| 624 | /// Returns a pointer that becomes invalid after any additions to the `InternPool`. | ||
| 625 | pub fn resolvedErrorSet(func: *const Func, ip: *const InternPool) *Index { | ||
| 626 | assert(func.analysis(ip).inferred_error_set); | ||
| 627 | return @ptrCast(&ip.extra.items[func.resolved_error_set_extra_index]); | ||
| 628 | } | ||
| 613 | }; | 629 | }; |
| 614 | 630 | ||
| 615 | pub const Int = struct { | 631 | pub const Int = struct { |
| ... | @@ -750,7 +766,7 @@ pub const Key = union(enum) { | ... | @@ -750,7 +766,7 @@ pub const Key = union(enum) { |
| 750 | }; | 766 | }; |
| 751 | 767 | ||
| 752 | pub fn hash32(key: Key, ip: *const InternPool) u32 { | 768 | pub fn hash32(key: Key, ip: *const InternPool) u32 { |
| 753 | return @as(u32, @truncate(key.hash64(ip))); | 769 | return @truncate(key.hash64(ip)); |
| 754 | } | 770 | } |
| 755 | 771 | ||
| 756 | pub fn hash64(key: Key, ip: *const InternPool) u64 { | 772 | pub fn hash64(key: Key, ip: *const InternPool) u64 { |
| ... | @@ -914,11 +930,7 @@ pub const Key = union(enum) { | ... | @@ -914,11 +930,7 @@ pub const Key = union(enum) { |
| 914 | return hasher.final(); | 930 | return hasher.final(); |
| 915 | }, | 931 | }, |
| 916 | 932 | ||
| 917 | .error_set_type => |error_set_type| { | 933 | .error_set_type => |x| Hash.hash(seed, std.mem.sliceAsBytes(x.names.get(ip))), |
| 918 | var hasher = Hash.init(seed); | ||
| 919 | for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem); | ||
| 920 | return hasher.final(); | ||
| 921 | }, | ||
| 922 | 934 | ||
| 923 | .anon_struct_type => |anon_struct_type| { | 935 | .anon_struct_type => |anon_struct_type| { |
| 924 | var hasher = Hash.init(seed); | 936 | var hasher = Hash.init(seed); |
| ... | @@ -1225,7 +1237,7 @@ pub const Key = union(enum) { | ... | @@ -1225,7 +1237,7 @@ pub const Key = union(enum) { |
| 1225 | }, | 1237 | }, |
| 1226 | .error_set_type => |a_info| { | 1238 | .error_set_type => |a_info| { |
| 1227 | const b_info = b.error_set_type; | 1239 | const b_info = b.error_set_type; |
| 1228 | return std.mem.eql(NullTerminatedString, a_info.names, b_info.names); | 1240 | return std.mem.eql(NullTerminatedString, a_info.names.get(ip), b_info.names.get(ip)); |
| 1229 | }, | 1241 | }, |
| 1230 | .inferred_error_set_type => |a_info| { | 1242 | .inferred_error_set_type => |a_info| { |
| 1231 | const b_info = b.inferred_error_set_type; | 1243 | const b_info = b.inferred_error_set_type; |
| ... | @@ -1518,13 +1530,14 @@ pub const Index = enum(u32) { | ... | @@ -1518,13 +1530,14 @@ pub const Index = enum(u32) { |
| 1518 | type_optional: DataIsIndex, | 1530 | type_optional: DataIsIndex, |
| 1519 | type_anyframe: DataIsIndex, | 1531 | type_anyframe: DataIsIndex, |
| 1520 | type_error_union: struct { data: *Key.ErrorUnionType }, | 1532 | type_error_union: struct { data: *Key.ErrorUnionType }, |
| 1533 | type_anyerror_union: DataIsIndex, | ||
| 1521 | type_error_set: struct { | 1534 | type_error_set: struct { |
| 1522 | const @"data.names_len" = opaque {}; | 1535 | const @"data.names_len" = opaque {}; |
| 1523 | data: *Tag.ErrorSet, | 1536 | data: *Tag.ErrorSet, |
| 1524 | @"trailing.names.len": *@"data.names_len", | 1537 | @"trailing.names.len": *@"data.names_len", |
| 1525 | trailing: struct { names: []NullTerminatedString }, | 1538 | trailing: struct { names: []NullTerminatedString }, |
| 1526 | }, | 1539 | }, |
| 1527 | type_inferred_error_set: struct { data: Module.InferredErrorSet.Index }, | 1540 | type_inferred_error_set: DataIsIndex, |
| 1528 | type_enum_auto: struct { | 1541 | type_enum_auto: struct { |
| 1529 | const @"data.fields_len" = opaque {}; | 1542 | const @"data.fields_len" = opaque {}; |
| 1530 | data: *EnumAuto, | 1543 | data: *EnumAuto, |
| ... | @@ -1916,11 +1929,14 @@ pub const Tag = enum(u8) { | ... | @@ -1916,11 +1929,14 @@ pub const Tag = enum(u8) { |
| 1916 | /// An error union type. | 1929 | /// An error union type. |
| 1917 | /// data is payload to `Key.ErrorUnionType`. | 1930 | /// data is payload to `Key.ErrorUnionType`. |
| 1918 | type_error_union, | 1931 | type_error_union, |
| 1932 | /// An error union type of the form `anyerror!T`. | ||
| 1933 | /// data is `Index` of payload type. | ||
| 1934 | type_anyerror_union, | ||
| 1919 | /// An error set type. | 1935 | /// An error set type. |
| 1920 | /// data is payload to `ErrorSet`. | 1936 | /// data is payload to `ErrorSet`. |
| 1921 | type_error_set, | 1937 | type_error_set, |
| 1922 | /// The inferred error set type of a function. | 1938 | /// The inferred error set type of a function. |
| 1923 | /// data is `Module.InferredErrorSet.Index`. | 1939 | /// data is `Index` of a `func_decl` or `func_instance`. |
| 1924 | type_inferred_error_set, | 1940 | type_inferred_error_set, |
| 1925 | /// An enum type with auto-numbered tag values. | 1941 | /// An enum type with auto-numbered tag values. |
| 1926 | /// The enum is exhaustive. | 1942 | /// The enum is exhaustive. |
| ... | @@ -2156,6 +2172,7 @@ pub const Tag = enum(u8) { | ... | @@ -2156,6 +2172,7 @@ pub const Tag = enum(u8) { |
| 2156 | .type_optional => unreachable, | 2172 | .type_optional => unreachable, |
| 2157 | .type_anyframe => unreachable, | 2173 | .type_anyframe => unreachable, |
| 2158 | .type_error_union => ErrorUnionType, | 2174 | .type_error_union => ErrorUnionType, |
| 2175 | .type_anyerror_union => unreachable, | ||
| 2159 | .type_error_set => ErrorSet, | 2176 | .type_error_set => ErrorSet, |
| 2160 | .type_inferred_error_set => unreachable, | 2177 | .type_inferred_error_set => unreachable, |
| 2161 | .type_enum_auto => EnumAuto, | 2178 | .type_enum_auto => EnumAuto, |
| ... | @@ -2251,6 +2268,10 @@ pub const Tag = enum(u8) { | ... | @@ -2251,6 +2268,10 @@ pub const Tag = enum(u8) { |
| 2251 | ty: Index, | 2268 | ty: Index, |
| 2252 | }; | 2269 | }; |
| 2253 | 2270 | ||
| 2271 | /// Trailing: | ||
| 2272 | /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which | ||
| 2273 | /// is a regular error set corresponding to the finished inferred error set. | ||
| 2274 | /// A `none` value marks that the inferred error set is not resolved yet. | ||
| 2254 | pub const FuncDecl = struct { | 2275 | pub const FuncDecl = struct { |
| 2255 | analysis: FuncAnalysis, | 2276 | analysis: FuncAnalysis, |
| 2256 | owner_decl: Module.Decl.Index, | 2277 | owner_decl: Module.Decl.Index, |
| ... | @@ -2263,10 +2284,10 @@ pub const Tag = enum(u8) { | ... | @@ -2263,10 +2284,10 @@ pub const Tag = enum(u8) { |
| 2263 | }; | 2284 | }; |
| 2264 | 2285 | ||
| 2265 | /// Trailing: | 2286 | /// Trailing: |
| 2266 | /// 0. For each parameter of generic_owner: Index | 2287 | /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which |
| 2267 | /// - comptime parameter: the comptime-known value | 2288 | /// is a regular error set corresponding to the finished inferred error set. |
| 2268 | /// - anytype parameter: the type of the runtime-known value | 2289 | /// A `none` value marks that the inferred error set is not resolved yet. |
| 2269 | /// - otherwise: `none` | 2290 | /// 1. For each parameter of generic_owner: `Index` if comptime, otherwise `none` |
| 2270 | pub const FuncInstance = struct { | 2291 | pub const FuncInstance = struct { |
| 2271 | analysis: FuncAnalysis, | 2292 | analysis: FuncAnalysis, |
| 2272 | // Needed by the linker for codegen. Not part of hashing or equality. | 2293 | // Needed by the linker for codegen. Not part of hashing or equality. |
| ... | @@ -2312,14 +2333,19 @@ pub const Tag = enum(u8) { | ... | @@ -2312,14 +2333,19 @@ pub const Tag = enum(u8) { |
| 2312 | }; | 2333 | }; |
| 2313 | 2334 | ||
| 2314 | /// State that is mutable during semantic analysis. This data is not used for | 2335 | /// State that is mutable during semantic analysis. This data is not used for |
| 2315 | /// equality or hashing. | 2336 | /// equality or hashing, except for `inferred_error_set` which is considered |
| 2337 | /// to be part of the type of the function. | ||
| 2316 | pub const FuncAnalysis = packed struct(u32) { | 2338 | pub const FuncAnalysis = packed struct(u32) { |
| 2317 | state: State, | 2339 | state: State, |
| 2318 | is_cold: bool, | 2340 | is_cold: bool, |
| 2319 | is_noinline: bool, | 2341 | is_noinline: bool, |
| 2320 | calls_or_awaits_errorable_fn: bool, | 2342 | calls_or_awaits_errorable_fn: bool, |
| 2321 | stack_alignment: Alignment, | 2343 | stack_alignment: Alignment, |
| 2322 | _: u15 = 0, | 2344 | |
| 2345 | /// True if this function has an inferred error set. | ||
| 2346 | inferred_error_set: bool, | ||
| 2347 | |||
| 2348 | _: u14 = 0, | ||
| 2323 | 2349 | ||
| 2324 | pub const State = enum(u8) { | 2350 | pub const State = enum(u8) { |
| 2325 | /// This function has not yet undergone analysis, because we have not | 2351 | /// This function has not yet undergone analysis, because we have not |
| ... | @@ -2710,9 +2736,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { | ... | @@ -2710,9 +2736,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 2710 | ip.unions_free_list.deinit(gpa); | 2736 | ip.unions_free_list.deinit(gpa); |
| 2711 | ip.allocated_unions.deinit(gpa); | 2737 | ip.allocated_unions.deinit(gpa); |
| 2712 | 2738 | ||
| 2713 | ip.inferred_error_sets_free_list.deinit(gpa); | ||
| 2714 | ip.allocated_inferred_error_sets.deinit(gpa); | ||
| 2715 | |||
| 2716 | ip.decls_free_list.deinit(gpa); | 2739 | ip.decls_free_list.deinit(gpa); |
| 2717 | ip.allocated_decls.deinit(gpa); | 2740 | ip.allocated_decls.deinit(gpa); |
| 2718 | 2741 | ||
| ... | @@ -2780,19 +2803,15 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -2780,19 +2803,15 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2780 | return .{ .ptr_type = ptr_info }; | 2803 | return .{ .ptr_type = ptr_info }; |
| 2781 | }, | 2804 | }, |
| 2782 | 2805 | ||
| 2783 | .type_optional => .{ .opt_type = @as(Index, @enumFromInt(data)) }, | 2806 | .type_optional => .{ .opt_type = @enumFromInt(data) }, |
| 2784 | .type_anyframe => .{ .anyframe_type = @as(Index, @enumFromInt(data)) }, | 2807 | .type_anyframe => .{ .anyframe_type = @enumFromInt(data) }, |
| 2785 | 2808 | ||
| 2786 | .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) }, | 2809 | .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) }, |
| 2787 | .type_error_set => { | 2810 | .type_anyerror_union => .{ .error_union_type = .{ |
| 2788 | const error_set = ip.extraDataTrail(Tag.ErrorSet, data); | 2811 | .error_set_type = .anyerror_type, |
| 2789 | const names_len = error_set.data.names_len; | 2812 | .payload_type = @enumFromInt(data), |
| 2790 | const names = ip.extra.items[error_set.end..][0..names_len]; | 2813 | } }, |
| 2791 | return .{ .error_set_type = .{ | 2814 | .type_error_set => ip.indexToKeyErrorSetType(data), |
| 2792 | .names = @ptrCast(names), | ||
| 2793 | .names_map = error_set.data.names_map.toOptional(), | ||
| 2794 | } }; | ||
| 2795 | }, | ||
| 2796 | .type_inferred_error_set => .{ | 2815 | .type_inferred_error_set => .{ |
| 2797 | .inferred_error_set_type = @enumFromInt(data), | 2816 | .inferred_error_set_type = @enumFromInt(data), |
| 2798 | }, | 2817 | }, |
| ... | @@ -2870,7 +2889,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -2870,7 +2889,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2870 | }, | 2889 | }, |
| 2871 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), | 2890 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), |
| 2872 | .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive), | 2891 | .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive), |
| 2873 | .type_function => .{ .func_type = ip.indexToKeyFuncType(data) }, | 2892 | .type_function => .{ .func_type = ip.extraFuncType(data) }, |
| 2874 | 2893 | ||
| 2875 | .undef => .{ .undef = @as(Index, @enumFromInt(data)) }, | 2894 | .undef => .{ .undef = @as(Index, @enumFromInt(data)) }, |
| 2876 | .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) }, | 2895 | .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) }, |
| ... | @@ -3117,12 +3136,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3117,12 +3136,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3117 | } }; | 3136 | } }; |
| 3118 | }, | 3137 | }, |
| 3119 | .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) }, | 3138 | .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) }, |
| 3120 | .func_instance => { | 3139 | .func_instance => .{ .func = ip.indexToKeyFuncInstance(data) }, |
| 3121 | @panic("TODO"); | 3140 | .func_decl => .{ .func = ip.indexToKeyFuncDecl(data) }, |
| 3122 | }, | ||
| 3123 | .func_decl => { | ||
| 3124 | @panic("TODO"); | ||
| 3125 | }, | ||
| 3126 | .only_possible_value => { | 3141 | .only_possible_value => { |
| 3127 | const ty = @as(Index, @enumFromInt(data)); | 3142 | const ty = @as(Index, @enumFromInt(data)); |
| 3128 | const ty_item = ip.items.get(@intFromEnum(ty)); | 3143 | const ty_item = ip.items.get(@intFromEnum(ty)); |
| ... | @@ -3227,8 +3242,19 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3227,8 +3242,19 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3227 | }; | 3242 | }; |
| 3228 | } | 3243 | } |
| 3229 | 3244 | ||
| 3230 | fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType { | 3245 | fn indexToKeyErrorSetType(ip: *const InternPool, data: u32) Key { |
| 3231 | const type_function = ip.extraDataTrail(Tag.TypeFunction, data); | 3246 | const error_set = ip.extraDataTrail(Tag.ErrorSet, data); |
| 3247 | return .{ .error_set_type = .{ | ||
| 3248 | .names = .{ | ||
| 3249 | .start = @intCast(error_set.end), | ||
| 3250 | .len = error_set.data.names_len, | ||
| 3251 | }, | ||
| 3252 | .names_map = error_set.data.names_map.toOptional(), | ||
| 3253 | } }; | ||
| 3254 | } | ||
| 3255 | |||
| 3256 | fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType { | ||
| 3257 | const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index); | ||
| 3232 | var index: usize = type_function.end; | 3258 | var index: usize = type_function.end; |
| 3233 | const comptime_bits: u32 = if (!type_function.data.flags.has_comptime_bits) 0 else b: { | 3259 | const comptime_bits: u32 = if (!type_function.data.flags.has_comptime_bits) 0 else b: { |
| 3234 | const x = ip.extra.items[index]; | 3260 | const x = ip.extra.items[index]; |
| ... | @@ -3256,14 +3282,22 @@ fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType { | ... | @@ -3256,14 +3282,22 @@ fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType { |
| 3256 | .cc_is_generic = type_function.data.flags.cc_is_generic, | 3282 | .cc_is_generic = type_function.data.flags.cc_is_generic, |
| 3257 | .section_is_generic = type_function.data.flags.section_is_generic, | 3283 | .section_is_generic = type_function.data.flags.section_is_generic, |
| 3258 | .addrspace_is_generic = type_function.data.flags.addrspace_is_generic, | 3284 | .addrspace_is_generic = type_function.data.flags.addrspace_is_generic, |
| 3259 | .is_generic = comptime_bits != 0 or | 3285 | .is_generic = type_function.data.flags.is_generic, |
| 3260 | type_function.data.flags.align_is_generic or | ||
| 3261 | type_function.data.flags.cc_is_generic or | ||
| 3262 | type_function.data.flags.section_is_generic or | ||
| 3263 | type_function.data.flags.addrspace_is_generic, | ||
| 3264 | }; | 3286 | }; |
| 3265 | } | 3287 | } |
| 3266 | 3288 | ||
| 3289 | fn indexToKeyFuncDecl(ip: *const InternPool, data: u32) Key.Func { | ||
| 3290 | _ = ip; | ||
| 3291 | _ = data; | ||
| 3292 | @panic("TODO"); | ||
| 3293 | } | ||
| 3294 | |||
| 3295 | fn indexToKeyFuncInstance(ip: *const InternPool, data: u32) Key.Func { | ||
| 3296 | _ = ip; | ||
| 3297 | _ = data; | ||
| 3298 | @panic("TODO"); | ||
| 3299 | } | ||
| 3300 | |||
| 3267 | fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key { | 3301 | fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key { |
| 3268 | const enum_explicit = ip.extraDataTrail(EnumExplicit, data); | 3302 | const enum_explicit = ip.extraDataTrail(EnumExplicit, data); |
| 3269 | const names = @as( | 3303 | const names = @as( |
| ... | @@ -3301,7 +3335,7 @@ fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key | ... | @@ -3301,7 +3335,7 @@ fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key |
| 3301 | pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | 3335 | pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3302 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 3336 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 3303 | const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); | 3337 | const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); |
| 3304 | if (gop.found_existing) return @as(Index, @enumFromInt(gop.index)); | 3338 | if (gop.found_existing) return @enumFromInt(gop.index); |
| 3305 | try ip.items.ensureUnusedCapacity(gpa, 1); | 3339 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 3306 | switch (key) { | 3340 | switch (key) { |
| 3307 | .int_type => |int_type| { | 3341 | .int_type => |int_type| { |
| ... | @@ -3392,17 +3426,20 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -3392,17 +3426,20 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3392 | }); | 3426 | }); |
| 3393 | }, | 3427 | }, |
| 3394 | .error_union_type => |error_union_type| { | 3428 | .error_union_type => |error_union_type| { |
| 3395 | ip.items.appendAssumeCapacity(.{ | 3429 | ip.items.appendAssumeCapacity(if (error_union_type.error_set_type == .anyerror_type) .{ |
| 3430 | .tag = .type_anyerror_union, | ||
| 3431 | .data = @intFromEnum(error_union_type.payload_type), | ||
| 3432 | } else .{ | ||
| 3396 | .tag = .type_error_union, | 3433 | .tag = .type_error_union, |
| 3397 | .data = try ip.addExtra(gpa, error_union_type), | 3434 | .data = try ip.addExtra(gpa, error_union_type), |
| 3398 | }); | 3435 | }); |
| 3399 | }, | 3436 | }, |
| 3400 | .error_set_type => |error_set_type| { | 3437 | .error_set_type => |error_set_type| { |
| 3401 | assert(error_set_type.names_map == .none); | 3438 | assert(error_set_type.names_map == .none); |
| 3402 | assert(std.sort.isSorted(NullTerminatedString, error_set_type.names, {}, NullTerminatedString.indexLessThan)); | 3439 | assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan)); |
| 3403 | const names_map = try ip.addMap(gpa); | 3440 | const names_map = try ip.addMap(gpa); |
| 3404 | try addStringsToMap(ip, gpa, names_map, error_set_type.names); | 3441 | try addStringsToMap(ip, gpa, names_map, error_set_type.names.get(ip)); |
| 3405 | const names_len = @as(u32, @intCast(error_set_type.names.len)); | 3442 | const names_len = error_set_type.names.len; |
| 3406 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names_len); | 3443 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names_len); |
| 3407 | ip.items.appendAssumeCapacity(.{ | 3444 | ip.items.appendAssumeCapacity(.{ |
| 3408 | .tag = .type_error_set, | 3445 | .tag = .type_error_set, |
| ... | @@ -3411,7 +3448,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -3411,7 +3448,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3411 | .names_map = names_map, | 3448 | .names_map = names_map, |
| 3412 | }), | 3449 | }), |
| 3413 | }); | 3450 | }); |
| 3414 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(error_set_type.names))); | 3451 | ip.extra.appendSliceAssumeCapacity(@ptrCast(error_set_type.names.get(ip))); |
| 3415 | }, | 3452 | }, |
| 3416 | .inferred_error_set_type => |ies_index| { | 3453 | .inferred_error_set_type => |ies_index| { |
| 3417 | ip.items.appendAssumeCapacity(.{ | 3454 | ip.items.appendAssumeCapacity(.{ |
| ... | @@ -4207,7 +4244,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -4207,7 +4244,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 4207 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values))); | 4244 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values))); |
| 4208 | }, | 4245 | }, |
| 4209 | } | 4246 | } |
| 4210 | return @as(Index, @enumFromInt(ip.items.len - 1)); | 4247 | return @enumFromInt(ip.items.len - 1); |
| 4211 | } | 4248 | } |
| 4212 | 4249 | ||
| 4213 | /// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`. | 4250 | /// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`. |
| ... | @@ -4216,13 +4253,13 @@ pub const GetFuncTypeKey = struct { | ... | @@ -4216,13 +4253,13 @@ pub const GetFuncTypeKey = struct { |
| 4216 | return_type: Index, | 4253 | return_type: Index, |
| 4217 | comptime_bits: u32, | 4254 | comptime_bits: u32, |
| 4218 | noalias_bits: u32, | 4255 | noalias_bits: u32, |
| 4219 | alignment: Alignment, | 4256 | /// `null` means generic. |
| 4220 | cc: std.builtin.CallingConvention, | 4257 | alignment: ?Alignment, |
| 4258 | /// `null` means generic. | ||
| 4259 | cc: ?std.builtin.CallingConvention, | ||
| 4221 | is_var_args: bool, | 4260 | is_var_args: bool, |
| 4222 | is_generic: bool, | 4261 | is_generic: bool, |
| 4223 | is_noinline: bool, | 4262 | is_noinline: bool, |
| 4224 | align_is_generic: bool, | ||
| 4225 | cc_is_generic: bool, | ||
| 4226 | section_is_generic: bool, | 4263 | section_is_generic: bool, |
| 4227 | addrspace_is_generic: bool, | 4264 | addrspace_is_generic: bool, |
| 4228 | }; | 4265 | }; |
| ... | @@ -4244,40 +4281,42 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat | ... | @@ -4244,40 +4281,42 @@ pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocat |
| 4244 | params_len); | 4281 | params_len); |
| 4245 | try ip.items.ensureUnusedCapacity(gpa, 1); | 4282 | try ip.items.ensureUnusedCapacity(gpa, 1); |
| 4246 | 4283 | ||
| 4247 | ip.items.appendAssumeCapacity(.{ | 4284 | const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{ |
| 4248 | .tag = .type_function, | 4285 | .params_len = params_len, |
| 4249 | .data = ip.addExtraAssumeCapacity(Tag.TypeFunction{ | 4286 | .return_type = key.return_type, |
| 4250 | .params_len = params_len, | 4287 | .flags = .{ |
| 4251 | .return_type = key.return_type, | 4288 | .alignment = key.alignment orelse .none, |
| 4252 | .flags = .{ | 4289 | .cc = key.cc orelse .Unspecified, |
| 4253 | .alignment = key.alignment, | 4290 | .is_var_args = key.is_var_args, |
| 4254 | .cc = key.cc, | 4291 | .has_comptime_bits = key.comptime_bits != 0, |
| 4255 | .is_var_args = key.is_var_args, | 4292 | .has_noalias_bits = key.noalias_bits != 0, |
| 4256 | .has_comptime_bits = key.comptime_bits != 0, | 4293 | .is_generic = key.is_generic, |
| 4257 | .has_noalias_bits = key.noalias_bits != 0, | 4294 | .is_noinline = key.is_noinline, |
| 4258 | .is_generic = key.is_generic, | 4295 | .align_is_generic = key.alignment == null, |
| 4259 | .is_noinline = key.is_noinline, | 4296 | .cc_is_generic = key.cc == null, |
| 4260 | .align_is_generic = key.align_is_generic, | 4297 | .section_is_generic = key.section_is_generic, |
| 4261 | .cc_is_generic = key.cc_is_generic, | 4298 | .addrspace_is_generic = key.addrspace_is_generic, |
| 4262 | .section_is_generic = key.section_is_generic, | 4299 | }, |
| 4263 | .addrspace_is_generic = key.addrspace_is_generic, | ||
| 4264 | }, | ||
| 4265 | }), | ||
| 4266 | }); | 4300 | }); |
| 4301 | |||
| 4267 | if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits); | 4302 | if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits); |
| 4268 | if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits); | 4303 | if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits); |
| 4269 | ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types)); | 4304 | ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types)); |
| 4270 | 4305 | ||
| 4271 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 4306 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 4272 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ | 4307 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ |
| 4273 | .func_type = indexToKeyFuncType(ip, @intCast(ip.items.len - 1)), | 4308 | .func_type = extraFuncType(ip, func_type_extra_index), |
| 4274 | }, adapter); | 4309 | }, adapter); |
| 4275 | if (!gop.found_existing) return @enumFromInt(ip.items.len - 1); | 4310 | if (gop.found_existing) { |
| 4311 | ip.extra.items.len = prev_extra_len; | ||
| 4312 | return @enumFromInt(gop.index); | ||
| 4313 | } | ||
| 4276 | 4314 | ||
| 4277 | // An existing function type was found; undo the additions to our two arrays. | 4315 | ip.items.appendAssumeCapacity(.{ |
| 4278 | ip.items.len -= 1; | 4316 | .tag = .type_function, |
| 4279 | ip.extra.items.len = prev_extra_len; | 4317 | .data = func_type_extra_index, |
| 4280 | return @enumFromInt(gop.index); | 4318 | }); |
| 4319 | return @enumFromInt(ip.items.len - 1); | ||
| 4281 | } | 4320 | } |
| 4282 | 4321 | ||
| 4283 | pub const GetExternFuncKey = struct { | 4322 | pub const GetExternFuncKey = struct { |
| ... | @@ -4299,19 +4338,71 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) All | ... | @@ -4299,19 +4338,71 @@ pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) All |
| 4299 | } | 4338 | } |
| 4300 | 4339 | ||
| 4301 | pub const GetFuncDeclKey = struct { | 4340 | pub const GetFuncDeclKey = struct { |
| 4302 | fn_owner_decl: Module.Decl.Index, | 4341 | owner_decl: Module.Decl.Index, |
| 4303 | param_types: []const Index, | 4342 | ty: Index, |
| 4343 | zir_body_inst: Zir.Inst.Index, | ||
| 4344 | lbrace_line: u32, | ||
| 4345 | rbrace_line: u32, | ||
| 4346 | lbrace_column: u32, | ||
| 4347 | rbrace_column: u32, | ||
| 4348 | cc: ?std.builtin.CallingConvention, | ||
| 4349 | is_noinline: bool, | ||
| 4350 | }; | ||
| 4351 | |||
| 4352 | pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index { | ||
| 4353 | // The strategy here is to add the function type unconditionally, then to | ||
| 4354 | // ask if it already exists, and if so, revert the lengths of the mutated | ||
| 4355 | // arrays. This is similar to what `getOrPutTrailingString` does. | ||
| 4356 | const prev_extra_len = ip.extra.items.len; | ||
| 4357 | |||
| 4358 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncDecl).Struct.fields.len); | ||
| 4359 | try ip.items.ensureUnusedCapacity(gpa, 1); | ||
| 4360 | |||
| 4361 | ip.items.appendAssumeCapacity(.{ | ||
| 4362 | .tag = .func_decl, | ||
| 4363 | .data = ip.addExtraAssumeCapacity(Tag.FuncDecl{ | ||
| 4364 | .analysis = .{ | ||
| 4365 | .state = if (key.cc == .Inline) .inline_only else .none, | ||
| 4366 | .is_cold = false, | ||
| 4367 | .is_noinline = key.is_noinline, | ||
| 4368 | .calls_or_awaits_errorable_fn = false, | ||
| 4369 | .stack_alignment = .none, | ||
| 4370 | .inferred_error_set = false, | ||
| 4371 | }, | ||
| 4372 | .owner_decl = key.owner_decl, | ||
| 4373 | .ty = key.ty, | ||
| 4374 | .zir_body_inst = key.zir_body_inst, | ||
| 4375 | .lbrace_line = key.lbrace_line, | ||
| 4376 | .rbrace_line = key.rbrace_line, | ||
| 4377 | .lbrace_column = key.lbrace_column, | ||
| 4378 | .rbrace_column = key.rbrace_column, | ||
| 4379 | }), | ||
| 4380 | }); | ||
| 4381 | |||
| 4382 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 4383 | const gop = try ip.map.getOrPutAdapted(gpa, Key{ | ||
| 4384 | .func = indexToKeyFuncDecl(ip, @intCast(ip.items.len - 1)), | ||
| 4385 | }, adapter); | ||
| 4386 | if (!gop.found_existing) return @enumFromInt(ip.items.len - 1); | ||
| 4387 | |||
| 4388 | // An existing function type was found; undo the additions to our two arrays. | ||
| 4389 | ip.items.len -= 1; | ||
| 4390 | ip.extra.items.len = prev_extra_len; | ||
| 4391 | return @enumFromInt(gop.index); | ||
| 4392 | } | ||
| 4393 | |||
| 4394 | pub const GetFuncDeclIesKey = struct { | ||
| 4395 | owner_decl: Module.Decl.Index, | ||
| 4396 | param_types: []Index, | ||
| 4304 | noalias_bits: u32, | 4397 | noalias_bits: u32, |
| 4305 | comptime_bits: u32, | 4398 | comptime_bits: u32, |
| 4306 | return_type: Index, | 4399 | bare_return_type: Index, |
| 4307 | inferred_error_set: bool, | ||
| 4308 | /// null means generic. | 4400 | /// null means generic. |
| 4309 | cc: ?std.builtin.CallingConvention, | 4401 | cc: ?std.builtin.CallingConvention, |
| 4310 | /// null means generic. | 4402 | /// null means generic. |
| 4311 | alignment: ?Alignment, | 4403 | alignment: ?Alignment, |
| 4312 | section: Section, | 4404 | section_is_generic: bool, |
| 4313 | /// null means generic | 4405 | addrspace_is_generic: bool, |
| 4314 | address_space: ?std.builtin.AddressSpace, | ||
| 4315 | is_var_args: bool, | 4406 | is_var_args: bool, |
| 4316 | is_generic: bool, | 4407 | is_generic: bool, |
| 4317 | is_noinline: bool, | 4408 | is_noinline: bool, |
| ... | @@ -4320,63 +4411,258 @@ pub const GetFuncDeclKey = struct { | ... | @@ -4320,63 +4411,258 @@ pub const GetFuncDeclKey = struct { |
| 4320 | rbrace_line: u32, | 4411 | rbrace_line: u32, |
| 4321 | lbrace_column: u32, | 4412 | lbrace_column: u32, |
| 4322 | rbrace_column: u32, | 4413 | rbrace_column: u32, |
| 4323 | |||
| 4324 | pub const Section = union(enum) { | ||
| 4325 | generic, | ||
| 4326 | default, | ||
| 4327 | explicit: InternPool.NullTerminatedString, | ||
| 4328 | }; | ||
| 4329 | }; | 4414 | }; |
| 4330 | 4415 | ||
| 4331 | pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index { | 4416 | pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) Allocator.Error!Index { |
| 4332 | const fn_owner_decl = ip.declPtr(key.fn_owner_decl); | 4417 | // Validate input parameters. |
| 4333 | const decl_index = try ip.createDecl(gpa, .{ | 4418 | assert(key.bare_return_type != .none); |
| 4334 | .name = undefined, | 4419 | for (key.param_types) |param_type| assert(param_type != .none); |
| 4335 | .src_namespace = fn_owner_decl.src_namespace, | 4420 | |
| 4336 | .src_node = fn_owner_decl.src_node, | 4421 | // The strategy here is to add the function decl unconditionally, then to |
| 4337 | .src_line = fn_owner_decl.src_line, | 4422 | // ask if it already exists, and if so, revert the lengths of the mutated |
| 4338 | .has_tv = true, | 4423 | // arrays. This is similar to what `getOrPutTrailingString` does. |
| 4339 | .owns_tv = true, | 4424 | const prev_extra_len = ip.extra.items.len; |
| 4340 | .ty = @panic("TODO"), | 4425 | const params_len: u32 = @intCast(key.param_types.len); |
| 4341 | .val = @panic("TODO"), | 4426 | |
| 4342 | .alignment = .none, | 4427 | try ip.map.ensureUnusedCapacity(gpa, 4); |
| 4343 | .@"linksection" = fn_owner_decl.@"linksection", | 4428 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncDecl).Struct.fields.len + |
| 4344 | .@"addrspace" = fn_owner_decl.@"addrspace", | 4429 | 1 + // inferred_error_set |
| 4345 | .analysis = .complete, | 4430 | @typeInfo(Tag.ErrorUnionType).Struct.fields.len + |
| 4346 | .deletion_flag = false, | 4431 | @typeInfo(Tag.TypeFunction).Struct.fields.len + |
| 4347 | .zir_decl_index = fn_owner_decl.zir_decl_index, | 4432 | @intFromBool(key.comptime_bits != 0) + |
| 4348 | .src_scope = fn_owner_decl.src_scope, | 4433 | @intFromBool(key.noalias_bits != 0) + |
| 4349 | .generation = 0, | 4434 | params_len); |
| 4350 | .is_pub = fn_owner_decl.is_pub, | 4435 | try ip.items.ensureUnusedCapacity(gpa, 4); |
| 4351 | .is_exported = fn_owner_decl.is_exported, | 4436 | |
| 4352 | .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace, | 4437 | ip.items.appendAssumeCapacity(.{ |
| 4353 | .has_align = fn_owner_decl.has_align, | 4438 | .tag = .func_decl, |
| 4354 | .alive = true, | 4439 | .data = ip.addExtraAssumeCapacity(Tag.FuncDecl{ |
| 4355 | .kind = .anon, | 4440 | .analysis = .{ |
| 4441 | .state = if (key.cc == .Inline) .inline_only else .none, | ||
| 4442 | .is_cold = false, | ||
| 4443 | .is_noinline = key.is_noinline, | ||
| 4444 | .calls_or_awaits_errorable_fn = false, | ||
| 4445 | .stack_alignment = .none, | ||
| 4446 | .inferred_error_set = true, | ||
| 4447 | }, | ||
| 4448 | .owner_decl = key.owner_decl, | ||
| 4449 | .ty = @enumFromInt(ip.items.len + 1), | ||
| 4450 | .zir_body_inst = key.zir_body_inst, | ||
| 4451 | .lbrace_line = key.lbrace_line, | ||
| 4452 | .rbrace_line = key.rbrace_line, | ||
| 4453 | .lbrace_column = key.lbrace_column, | ||
| 4454 | .rbrace_column = key.rbrace_column, | ||
| 4455 | }), | ||
| 4456 | }); | ||
| 4457 | ip.extra.appendAssumeCapacity(@intFromEnum(Index.none)); | ||
| 4458 | |||
| 4459 | ip.items.appendAssumeCapacity(.{ | ||
| 4460 | .tag = .type_error_union, | ||
| 4461 | .data = ip.addExtraAssumeCapacity(Tag.ErrorUnionType{ | ||
| 4462 | .error_set_type = @enumFromInt(ip.items.len + 1), | ||
| 4463 | .payload_type = key.bare_return_type, | ||
| 4464 | }), | ||
| 4356 | }); | 4465 | }); |
| 4357 | // TODO better names for generic function instantiations | 4466 | |
| 4358 | const decl_name = try ip.getOrPutStringFmt(gpa, "{}__anon_{d}", .{ | 4467 | ip.items.appendAssumeCapacity(.{ |
| 4359 | fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), | 4468 | .tag = .type_inferred_error_set, |
| 4469 | .data = @intCast(ip.items.len - 2), | ||
| 4360 | }); | 4470 | }); |
| 4361 | ip.declPtr(decl_index).name = decl_name; | 4471 | |
| 4362 | @panic("TODO"); | 4472 | const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{ |
| 4473 | .params_len = params_len, | ||
| 4474 | .return_type = @enumFromInt(ip.items.len - 2), | ||
| 4475 | .flags = .{ | ||
| 4476 | .alignment = key.alignment orelse .none, | ||
| 4477 | .cc = key.cc orelse .Unspecified, | ||
| 4478 | .is_var_args = key.is_var_args, | ||
| 4479 | .has_comptime_bits = key.comptime_bits != 0, | ||
| 4480 | .has_noalias_bits = key.noalias_bits != 0, | ||
| 4481 | .is_generic = key.is_generic, | ||
| 4482 | .is_noinline = key.is_noinline, | ||
| 4483 | .align_is_generic = key.alignment == null, | ||
| 4484 | .cc_is_generic = key.cc == null, | ||
| 4485 | .section_is_generic = key.section_is_generic, | ||
| 4486 | .addrspace_is_generic = key.addrspace_is_generic, | ||
| 4487 | }, | ||
| 4488 | }); | ||
| 4489 | if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits); | ||
| 4490 | if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits); | ||
| 4491 | ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types)); | ||
| 4492 | |||
| 4493 | ip.items.appendAssumeCapacity(.{ | ||
| 4494 | .tag = .type_function, | ||
| 4495 | .data = func_type_extra_index, | ||
| 4496 | }); | ||
| 4497 | |||
| 4498 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 4499 | const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4500 | .func = indexToKeyFuncDecl(ip, @intCast(ip.items.len - 4)), | ||
| 4501 | }, adapter); | ||
| 4502 | if (!gop.found_existing) { | ||
| 4503 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ .error_union_type = .{ | ||
| 4504 | .error_set_type = @enumFromInt(ip.items.len - 2), | ||
| 4505 | .payload_type = key.bare_return_type, | ||
| 4506 | } }, adapter).found_existing); | ||
| 4507 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4508 | .inferred_error_set_type = @enumFromInt(ip.items.len - 4), | ||
| 4509 | }, adapter).found_existing); | ||
| 4510 | assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ | ||
| 4511 | .func_type = extraFuncType(ip, func_type_extra_index), | ||
| 4512 | }, adapter).found_existing); | ||
| 4513 | return @enumFromInt(ip.items.len - 4); | ||
| 4514 | } | ||
| 4515 | |||
| 4516 | // An existing function type was found; undo the additions to our two arrays. | ||
| 4517 | ip.items.len -= 4; | ||
| 4518 | ip.extra.items.len = prev_extra_len; | ||
| 4519 | return @enumFromInt(gop.index); | ||
| 4520 | } | ||
| 4521 | |||
| 4522 | pub fn getErrorSetType( | ||
| 4523 | ip: *InternPool, | ||
| 4524 | gpa: Allocator, | ||
| 4525 | names: []const NullTerminatedString, | ||
| 4526 | ) Allocator.Error!Index { | ||
| 4527 | assert(std.sort.isSorted(NullTerminatedString, names, {}, NullTerminatedString.indexLessThan)); | ||
| 4528 | |||
| 4529 | // The strategy here is to add the type unconditionally, then to ask if it | ||
| 4530 | // already exists, and if so, revert the lengths of the mutated arrays. | ||
| 4531 | // This is similar to what `getOrPutTrailingString` does. | ||
| 4532 | const prev_extra_len = ip.extra.items.len; | ||
| 4533 | |||
| 4534 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names.len); | ||
| 4535 | try ip.items.ensureUnusedCapacity(gpa, 1); | ||
| 4536 | |||
| 4537 | ip.items.appendAssumeCapacity(.{ | ||
| 4538 | .tag = .type_error_set, | ||
| 4539 | .data = ip.addExtraAssumeCapacity(Tag.ErrorSet{ | ||
| 4540 | .names_len = @intCast(names.len), | ||
| 4541 | .names_map = @enumFromInt(ip.maps.items.len), | ||
| 4542 | }), | ||
| 4543 | }); | ||
| 4544 | ip.extra.appendSliceAssumeCapacity(@ptrCast(names)); | ||
| 4545 | |||
| 4546 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | ||
| 4547 | const key = indexToKeyErrorSetType(ip, @intCast(ip.items.len - 1)); | ||
| 4548 | const gop = try ip.map.getOrPutAdapted(gpa, key, adapter); | ||
| 4549 | if (!gop.found_existing) { | ||
| 4550 | _ = ip.addMap(gpa) catch { | ||
| 4551 | ip.items.len -= 1; | ||
| 4552 | ip.extra.items.len = prev_extra_len; | ||
| 4553 | }; | ||
| 4554 | return @enumFromInt(ip.items.len - 1); | ||
| 4555 | } | ||
| 4556 | |||
| 4557 | // An existing function type was found; undo the additions to our two arrays. | ||
| 4558 | ip.items.len -= 1; | ||
| 4559 | ip.extra.items.len = prev_extra_len; | ||
| 4560 | return @enumFromInt(gop.index); | ||
| 4363 | } | 4561 | } |
| 4364 | 4562 | ||
| 4365 | pub const GetFuncInstanceKey = struct { | 4563 | pub const GetFuncInstanceKey = struct { |
| 4366 | param_types: []const Index, | 4564 | param_types: []Index, |
| 4367 | noalias_bits: u32, | 4565 | noalias_bits: u32, |
| 4368 | return_type: Index, | 4566 | bare_return_type: Index, |
| 4369 | cc: std.builtin.CallingConvention, | 4567 | cc: std.builtin.CallingConvention, |
| 4370 | alignment: Alignment, | 4568 | alignment: Alignment, |
| 4371 | is_noinline: bool, | 4569 | is_noinline: bool, |
| 4372 | generic_owner: Index, | 4570 | generic_owner: Index, |
| 4571 | inferred_error_set: bool, | ||
| 4373 | }; | 4572 | }; |
| 4374 | 4573 | ||
| 4375 | pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, key: GetFuncInstanceKey) Allocator.Error!Index { | 4574 | pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index { |
| 4376 | _ = ip; | 4575 | _ = ip; |
| 4377 | _ = gpa; | 4576 | _ = gpa; |
| 4378 | _ = key; | 4577 | _ = arg; |
| 4379 | @panic("TODO"); | 4578 | @panic("TODO"); |
| 4579 | //const func_ty = try ip.getFuncType(gpa, .{ | ||
| 4580 | // .param_types = arg.param_types, | ||
| 4581 | // .bare_return_type = arg.bare_return_type, | ||
| 4582 | // .comptime_bits = arg.comptime_bits, | ||
| 4583 | // .noalias_bits = arg.noalias_bits, | ||
| 4584 | // .alignment = arg.alignment, | ||
| 4585 | // .cc = arg.cc, | ||
| 4586 | // .is_var_args = arg.is_var_args, | ||
| 4587 | // .is_generic = arg.is_generic, | ||
| 4588 | // .is_noinline = arg.is_noinline, | ||
| 4589 | // .section_is_generic = arg.section_is_generic, | ||
| 4590 | // .addrspace_is_generic = arg.addrspace_is_generic, | ||
| 4591 | // .inferred_error_set = arg.inferred_error_set, | ||
| 4592 | //}); | ||
| 4593 | |||
| 4594 | //const fn_owner_decl = ip.declPtr(arg.fn_owner_decl); | ||
| 4595 | //const decl_index = try ip.createDecl(gpa, .{ | ||
| 4596 | // .name = undefined, | ||
| 4597 | // .src_namespace = fn_owner_decl.src_namespace, | ||
| 4598 | // .src_node = fn_owner_decl.src_node, | ||
| 4599 | // .src_line = fn_owner_decl.src_line, | ||
| 4600 | // .has_tv = true, | ||
| 4601 | // .owns_tv = true, | ||
| 4602 | // .ty = func_ty, | ||
| 4603 | // .val = undefined, | ||
| 4604 | // .alignment = .none, | ||
| 4605 | // .@"linksection" = fn_owner_decl.@"linksection", | ||
| 4606 | // .@"addrspace" = fn_owner_decl.@"addrspace", | ||
| 4607 | // .analysis = .complete, | ||
| 4608 | // .deletion_flag = false, | ||
| 4609 | // .zir_decl_index = fn_owner_decl.zir_decl_index, | ||
| 4610 | // .src_scope = fn_owner_decl.src_scope, | ||
| 4611 | // .generation = arg.generation, | ||
| 4612 | // .is_pub = fn_owner_decl.is_pub, | ||
| 4613 | // .is_exported = fn_owner_decl.is_exported, | ||
| 4614 | // .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace, | ||
| 4615 | // .has_align = fn_owner_decl.has_align, | ||
| 4616 | // .alive = true, | ||
| 4617 | // .kind = .anon, | ||
| 4618 | //}); | ||
| 4619 | //// TODO: improve this name | ||
| 4620 | //const decl = ip.declPtr(decl_index); | ||
| 4621 | //decl.name = try ip.getOrPutStringFmt(gpa, "{}__anon_{d}", .{ | ||
| 4622 | // fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), | ||
| 4623 | //}); | ||
| 4624 | |||
| 4625 | //const gop = try ip.map.getOrPutAdapted(gpa, Key{ | ||
| 4626 | // .func = .{ | ||
| 4627 | // .ty = func_ty, | ||
| 4628 | // .generic_owner = .none, | ||
| 4629 | // .owner_decl = decl_index, | ||
| 4630 | // // Only the above fields will be read for hashing/equality. | ||
| 4631 | // .analysis_extra_index = undefined, | ||
| 4632 | // .zir_body_inst_extra_index = undefined, | ||
| 4633 | // .branch_quota_extra_index = undefined, | ||
| 4634 | // .resolved_error_set_extra_index = undefined, | ||
| 4635 | // .zir_body_inst = undefined, | ||
| 4636 | // .lbrace_line = undefined, | ||
| 4637 | // .rbrace_line = undefined, | ||
| 4638 | // .lbrace_column = undefined, | ||
| 4639 | // .rbrace_column = undefined, | ||
| 4640 | // .comptime_args = undefined, | ||
| 4641 | // }, | ||
| 4642 | //}, KeyAdapter{ .intern_pool = ip }); | ||
| 4643 | //if (gop.found_existing) return @enumFromInt(gop.index); | ||
| 4644 | //try ip.items.append(gpa, .{ | ||
| 4645 | // .tag = .func_decl, | ||
| 4646 | // .data = try ip.addExtra(gpa, .{ | ||
| 4647 | // .analysis = .{ | ||
| 4648 | // .state = if (arg.cc == .Inline) .inline_only else .none, | ||
| 4649 | // .is_cold = false, | ||
| 4650 | // .is_noinline = arg.is_noinline, | ||
| 4651 | // .calls_or_awaits_errorable_fn = false, | ||
| 4652 | // .stack_alignment = .none, | ||
| 4653 | // }, | ||
| 4654 | // .owner_decl = arg.owner_decl, | ||
| 4655 | // .ty = func_ty, | ||
| 4656 | // .zir_body_inst = arg.zir_body_inst, | ||
| 4657 | // .lbrace_line = arg.lbrace_line, | ||
| 4658 | // .rbrace_line = arg.rbrace_line, | ||
| 4659 | // .lbrace_column = arg.lbrace_column, | ||
| 4660 | // .rbrace_column = arg.rbrace_column, | ||
| 4661 | // }), | ||
| 4662 | //}); | ||
| 4663 | //const func_index: InternPool.Index = @enumFromInt(ip.items.len - 1); | ||
| 4664 | //decl.val = func_index.toValue(); | ||
| 4665 | //return func_index; | ||
| 4380 | } | 4666 | } |
| 4381 | 4667 | ||
| 4382 | /// Provides API for completing an enum type after calling `getIncompleteEnum`. | 4668 | /// Provides API for completing an enum type after calling `getIncompleteEnum`. |
| ... | @@ -4576,15 +4862,15 @@ pub fn finishGetEnum( | ... | @@ -4576,15 +4862,15 @@ pub fn finishGetEnum( |
| 4576 | .values_map = values_map, | 4862 | .values_map = values_map, |
| 4577 | }), | 4863 | }), |
| 4578 | }); | 4864 | }); |
| 4579 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.names))); | 4865 | ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.names)); |
| 4580 | ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.values))); | 4866 | ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.values)); |
| 4581 | return @as(Index, @enumFromInt(ip.items.len - 1)); | 4867 | return @enumFromInt(ip.items.len - 1); |
| 4582 | } | 4868 | } |
| 4583 | 4869 | ||
| 4584 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { | 4870 | pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { |
| 4585 | const adapter: KeyAdapter = .{ .intern_pool = ip }; | 4871 | const adapter: KeyAdapter = .{ .intern_pool = ip }; |
| 4586 | const index = ip.map.getIndexAdapted(key, adapter) orelse return null; | 4872 | const index = ip.map.getIndexAdapted(key, adapter) orelse return null; |
| 4587 | return @as(Index, @enumFromInt(index)); | 4873 | return @enumFromInt(index); |
| 4588 | } | 4874 | } |
| 4589 | 4875 | ||
| 4590 | pub fn getAssumeExists(ip: *const InternPool, key: Key) Index { | 4876 | pub fn getAssumeExists(ip: *const InternPool, key: Key) Index { |
| ... | @@ -4622,7 +4908,7 @@ fn addIndexesToMap( | ... | @@ -4622,7 +4908,7 @@ fn addIndexesToMap( |
| 4622 | fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex { | 4908 | fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex { |
| 4623 | const ptr = try ip.maps.addOne(gpa); | 4909 | const ptr = try ip.maps.addOne(gpa); |
| 4624 | ptr.* = .{}; | 4910 | ptr.* = .{}; |
| 4625 | return @as(MapIndex, @enumFromInt(ip.maps.items.len - 1)); | 4911 | return @enumFromInt(ip.maps.items.len - 1); |
| 4626 | } | 4912 | } |
| 4627 | 4913 | ||
| 4628 | /// This operation only happens under compile error conditions. | 4914 | /// This operation only happens under compile error conditions. |
| ... | @@ -4653,23 +4939,28 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { | ... | @@ -4653,23 +4939,28 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 4653 | const result = @as(u32, @intCast(ip.extra.items.len)); | 4939 | const result = @as(u32, @intCast(ip.extra.items.len)); |
| 4654 | inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { | 4940 | inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { |
| 4655 | ip.extra.appendAssumeCapacity(switch (field.type) { | 4941 | ip.extra.appendAssumeCapacity(switch (field.type) { |
| 4656 | u32 => @field(extra, field.name), | 4942 | Index, |
| 4657 | Index => @intFromEnum(@field(extra, field.name)), | 4943 | Module.Decl.Index, |
| 4658 | Module.Decl.Index => @intFromEnum(@field(extra, field.name)), | 4944 | Module.Namespace.Index, |
| 4659 | Module.Namespace.Index => @intFromEnum(@field(extra, field.name)), | 4945 | Module.Namespace.OptionalIndex, |
| 4660 | Module.Namespace.OptionalIndex => @intFromEnum(@field(extra, field.name)), | 4946 | MapIndex, |
| 4661 | MapIndex => @intFromEnum(@field(extra, field.name)), | 4947 | OptionalMapIndex, |
| 4662 | OptionalMapIndex => @intFromEnum(@field(extra, field.name)), | 4948 | RuntimeIndex, |
| 4663 | RuntimeIndex => @intFromEnum(@field(extra, field.name)), | 4949 | String, |
| 4664 | String => @intFromEnum(@field(extra, field.name)), | 4950 | NullTerminatedString, |
| 4665 | NullTerminatedString => @intFromEnum(@field(extra, field.name)), | 4951 | OptionalNullTerminatedString, |
| 4666 | OptionalNullTerminatedString => @intFromEnum(@field(extra, field.name)), | 4952 | Tag.TypePointer.VectorIndex, |
| 4667 | i32 => @as(u32, @bitCast(@field(extra, field.name))), | 4953 | => @intFromEnum(@field(extra, field.name)), |
| 4668 | Tag.TypePointer.Flags => @as(u32, @bitCast(@field(extra, field.name))), | 4954 | |
| 4669 | Tag.TypeFunction.Flags => @as(u32, @bitCast(@field(extra, field.name))), | 4955 | u32, |
| 4670 | Tag.TypePointer.PackedOffset => @as(u32, @bitCast(@field(extra, field.name))), | 4956 | i32, |
| 4671 | Tag.TypePointer.VectorIndex => @intFromEnum(@field(extra, field.name)), | 4957 | FuncAnalysis, |
| 4672 | Tag.Variable.Flags => @as(u32, @bitCast(@field(extra, field.name))), | 4958 | Tag.TypePointer.Flags, |
| 4959 | Tag.TypeFunction.Flags, | ||
| 4960 | Tag.TypePointer.PackedOffset, | ||
| 4961 | Tag.Variable.Flags, | ||
| 4962 | => @bitCast(@field(extra, field.name)), | ||
| 4963 | |||
| 4673 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 4964 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 4674 | }); | 4965 | }); |
| 4675 | } | 4966 | } |
| ... | @@ -4720,8 +5011,6 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct | ... | @@ -4720,8 +5011,6 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct |
| 4720 | inline for (fields, 0..) |field, i| { | 5011 | inline for (fields, 0..) |field, i| { |
| 4721 | const int32 = ip.extra.items[i + index]; | 5012 | const int32 = ip.extra.items[i + index]; |
| 4722 | @field(result, field.name) = switch (field.type) { | 5013 | @field(result, field.name) = switch (field.type) { |
| 4723 | u32 => int32, | ||
| 4724 | |||
| 4725 | Index, | 5014 | Index, |
| 4726 | Module.Decl.Index, | 5015 | Module.Decl.Index, |
| 4727 | Module.Namespace.Index, | 5016 | Module.Namespace.Index, |
| ... | @@ -4735,6 +5024,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct | ... | @@ -4735,6 +5024,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct |
| 4735 | Tag.TypePointer.VectorIndex, | 5024 | Tag.TypePointer.VectorIndex, |
| 4736 | => @enumFromInt(int32), | 5025 | => @enumFromInt(int32), |
| 4737 | 5026 | ||
| 5027 | u32, | ||
| 4738 | i32, | 5028 | i32, |
| 4739 | Tag.TypePointer.Flags, | 5029 | Tag.TypePointer.Flags, |
| 4740 | Tag.TypeFunction.Flags, | 5030 | Tag.TypeFunction.Flags, |
| ... | @@ -5200,19 +5490,11 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType { | ... | @@ -5200,19 +5490,11 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType { |
| 5200 | const tags = ip.items.items(.tag); | 5490 | const tags = ip.items.items(.tag); |
| 5201 | const datas = ip.items.items(.data); | 5491 | const datas = ip.items.items(.data); |
| 5202 | switch (tags[@intFromEnum(val)]) { | 5492 | switch (tags[@intFromEnum(val)]) { |
| 5203 | .type_function => return indexToKeyFuncType(ip, datas[@intFromEnum(val)]), | 5493 | .type_function => return extraFuncType(ip, datas[@intFromEnum(val)]), |
| 5204 | else => return null, | 5494 | else => return null, |
| 5205 | } | 5495 | } |
| 5206 | } | 5496 | } |
| 5207 | 5497 | ||
| 5208 | pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.InferredErrorSet.OptionalIndex { | ||
| 5209 | assert(val != .none); | ||
| 5210 | const tags = ip.items.items(.tag); | ||
| 5211 | if (tags[@intFromEnum(val)] != .type_inferred_error_set) return .none; | ||
| 5212 | const datas = ip.items.items(.data); | ||
| 5213 | return @as(Module.InferredErrorSet.Index, @enumFromInt(datas[@intFromEnum(val)])).toOptional(); | ||
| 5214 | } | ||
| 5215 | |||
| 5216 | /// includes .comptime_int_type | 5498 | /// includes .comptime_int_type |
| 5217 | pub fn isIntegerType(ip: *const InternPool, ty: Index) bool { | 5499 | pub fn isIntegerType(ip: *const InternPool, ty: Index) bool { |
| 5218 | return switch (ty) { | 5500 | return switch (ty) { |
| ... | @@ -5284,6 +5566,10 @@ pub fn isAggregateType(ip: *const InternPool, ty: Index) bool { | ... | @@ -5284,6 +5566,10 @@ pub fn isAggregateType(ip: *const InternPool, ty: Index) bool { |
| 5284 | }; | 5566 | }; |
| 5285 | } | 5567 | } |
| 5286 | 5568 | ||
| 5569 | pub fn errorUnionSet(ip: *const InternPool, ty: Index) Index { | ||
| 5570 | return ip.indexToKey(ty).error_union_type.error_set_type; | ||
| 5571 | } | ||
| 5572 | |||
| 5287 | /// The is only legal because the initializer is not part of the hash. | 5573 | /// The is only legal because the initializer is not part of the hash. |
| 5288 | pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void { | 5574 | pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void { |
| 5289 | const item = ip.items.get(@intFromEnum(index)); | 5575 | const item = ip.items.get(@intFromEnum(index)); |
| ... | @@ -5354,11 +5640,12 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -5354,11 +5640,12 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 5354 | .type_optional => 0, | 5640 | .type_optional => 0, |
| 5355 | .type_anyframe => 0, | 5641 | .type_anyframe => 0, |
| 5356 | .type_error_union => @sizeOf(Key.ErrorUnionType), | 5642 | .type_error_union => @sizeOf(Key.ErrorUnionType), |
| 5643 | .type_anyerror_union => 0, | ||
| 5357 | .type_error_set => b: { | 5644 | .type_error_set => b: { |
| 5358 | const info = ip.extraData(Tag.ErrorSet, data); | 5645 | const info = ip.extraData(Tag.ErrorSet, data); |
| 5359 | break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len); | 5646 | break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len); |
| 5360 | }, | 5647 | }, |
| 5361 | .type_inferred_error_set => @sizeOf(Module.InferredErrorSet), | 5648 | .type_inferred_error_set => 0, |
| 5362 | .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit), | 5649 | .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit), |
| 5363 | .type_enum_auto => @sizeOf(EnumAuto), | 5650 | .type_enum_auto => @sizeOf(EnumAuto), |
| 5364 | .type_opaque => @sizeOf(Key.OpaqueType), | 5651 | .type_opaque => @sizeOf(Key.OpaqueType), |
| ... | @@ -5506,6 +5793,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -5506,6 +5793,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 5506 | .type_optional, | 5793 | .type_optional, |
| 5507 | .type_anyframe, | 5794 | .type_anyframe, |
| 5508 | .type_error_union, | 5795 | .type_error_union, |
| 5796 | .type_anyerror_union, | ||
| 5509 | .type_error_set, | 5797 | .type_error_set, |
| 5510 | .type_inferred_error_set, | 5798 | .type_inferred_error_set, |
| 5511 | .type_enum_explicit, | 5799 | .type_enum_explicit, |
| ... | @@ -5598,14 +5886,6 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo | ... | @@ -5598,14 +5886,6 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo |
| 5598 | return ip.allocated_unions.at(@intFromEnum(index)); | 5886 | return ip.allocated_unions.at(@intFromEnum(index)); |
| 5599 | } | 5887 | } |
| 5600 | 5888 | ||
| 5601 | pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.InferredErrorSet.Index) *Module.InferredErrorSet { | ||
| 5602 | return ip.allocated_inferred_error_sets.at(@intFromEnum(index)); | ||
| 5603 | } | ||
| 5604 | |||
| 5605 | pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.InferredErrorSet.Index) *const Module.InferredErrorSet { | ||
| 5606 | return ip.allocated_inferred_error_sets.at(@intFromEnum(index)); | ||
| 5607 | } | ||
| 5608 | |||
| 5609 | pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl { | 5889 | pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl { |
| 5610 | return ip.allocated_decls.at(@intFromEnum(index)); | 5890 | return ip.allocated_decls.at(@intFromEnum(index)); |
| 5611 | } | 5891 | } |
| ... | @@ -5658,28 +5938,6 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) | ... | @@ -5658,28 +5938,6 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) |
| 5658 | }; | 5938 | }; |
| 5659 | } | 5939 | } |
| 5660 | 5940 | ||
| 5661 | pub fn createInferredErrorSet( | ||
| 5662 | ip: *InternPool, | ||
| 5663 | gpa: Allocator, | ||
| 5664 | initialization: Module.InferredErrorSet, | ||
| 5665 | ) Allocator.Error!Module.InferredErrorSet.Index { | ||
| 5666 | if (ip.inferred_error_sets_free_list.popOrNull()) |index| { | ||
| 5667 | ip.allocated_inferred_error_sets.at(@intFromEnum(index)).* = initialization; | ||
| 5668 | return index; | ||
| 5669 | } | ||
| 5670 | const ptr = try ip.allocated_inferred_error_sets.addOne(gpa); | ||
| 5671 | ptr.* = initialization; | ||
| 5672 | return @as(Module.InferredErrorSet.Index, @enumFromInt(ip.allocated_inferred_error_sets.len - 1)); | ||
| 5673 | } | ||
| 5674 | |||
| 5675 | pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.InferredErrorSet.Index) void { | ||
| 5676 | ip.inferredErrorSetPtr(index).* = undefined; | ||
| 5677 | ip.inferred_error_sets_free_list.append(gpa, index) catch { | ||
| 5678 | // In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory | ||
| 5679 | // allocation failures here, instead leaking the InferredErrorSet until garbage collection. | ||
| 5680 | }; | ||
| 5681 | } | ||
| 5682 | |||
| 5683 | pub fn createDecl( | 5941 | pub fn createDecl( |
| 5684 | ip: *InternPool, | 5942 | ip: *InternPool, |
| 5685 | gpa: Allocator, | 5943 | gpa: Allocator, |
| ... | @@ -5912,6 +6170,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -5912,6 +6170,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 5912 | .type_optional, | 6170 | .type_optional, |
| 5913 | .type_anyframe, | 6171 | .type_anyframe, |
| 5914 | .type_error_union, | 6172 | .type_error_union, |
| 6173 | .type_anyerror_union, | ||
| 5915 | .type_error_set, | 6174 | .type_error_set, |
| 5916 | .type_inferred_error_set, | 6175 | .type_inferred_error_set, |
| 5917 | .type_enum_auto, | 6176 | .type_enum_auto, |
| ... | @@ -6236,7 +6495,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -6236,7 +6495,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 6236 | 6495 | ||
| 6237 | .type_optional => .Optional, | 6496 | .type_optional => .Optional, |
| 6238 | .type_anyframe => .AnyFrame, | 6497 | .type_anyframe => .AnyFrame, |
| 6239 | .type_error_union => .ErrorUnion, | 6498 | |
| 6499 | .type_error_union, | ||
| 6500 | .type_anyerror_union, | ||
| 6501 | => .ErrorUnion, | ||
| 6240 | 6502 | ||
| 6241 | .type_error_set, | 6503 | .type_error_set, |
| 6242 | .type_inferred_error_set, | 6504 | .type_inferred_error_set, |
| ... | @@ -6340,6 +6602,10 @@ pub fn funcAnalysis(ip: *const InternPool, i: Index) *FuncAnalysis { | ... | @@ -6340,6 +6602,10 @@ pub fn funcAnalysis(ip: *const InternPool, i: Index) *FuncAnalysis { |
| 6340 | return @ptrCast(&ip.extra.items[extra_index]); | 6602 | return @ptrCast(&ip.extra.items[extra_index]); |
| 6341 | } | 6603 | } |
| 6342 | 6604 | ||
| 6605 | pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool { | ||
| 6606 | return funcAnalysis(ip, i).inferred_error_set; | ||
| 6607 | } | ||
| 6608 | |||
| 6343 | pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { | 6609 | pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { |
| 6344 | assert(i != .none); | 6610 | assert(i != .none); |
| 6345 | const item = ip.items.get(@intFromEnum(i)); | 6611 | const item = ip.items.get(@intFromEnum(i)); |
| ... | @@ -6356,3 +6622,43 @@ pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { | ... | @@ -6356,3 +6622,43 @@ pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { |
| 6356 | }; | 6622 | }; |
| 6357 | return ip.extra.items[extra_index]; | 6623 | return ip.extra.items[extra_index]; |
| 6358 | } | 6624 | } |
| 6625 | |||
| 6626 | pub fn iesFuncIndex(ip: *const InternPool, ies_index: InternPool.Index) InternPool.Index { | ||
| 6627 | assert(ies_index != .none); | ||
| 6628 | const tags = ip.items.items(.tag); | ||
| 6629 | assert(tags[@intFromEnum(ies_index)] == .type_inferred_error_set); | ||
| 6630 | const func_index = ip.items.items(.data)[@intFromEnum(ies_index)]; | ||
| 6631 | switch (tags[func_index]) { | ||
| 6632 | .func_decl, .func_instance => {}, | ||
| 6633 | else => unreachable, // assertion failed | ||
| 6634 | } | ||
| 6635 | return @enumFromInt(func_index); | ||
| 6636 | } | ||
| 6637 | |||
| 6638 | /// Returns a mutable pointer to the resolved error set type of an inferred | ||
| 6639 | /// error set function. The returned pointer is invalidated when anything is | ||
| 6640 | /// added to `ip`. | ||
| 6641 | pub fn iesResolved(ip: *const InternPool, ies_index: InternPool.Index) *InternPool.Index { | ||
| 6642 | assert(ies_index != .none); | ||
| 6643 | const tags = ip.items.items(.tag); | ||
| 6644 | const datas = ip.items.items(.data); | ||
| 6645 | assert(tags[@intFromEnum(ies_index)] == .type_inferred_error_set); | ||
| 6646 | const func_index = datas[@intFromEnum(ies_index)]; | ||
| 6647 | return funcIesResolved(ip, func_index); | ||
| 6648 | } | ||
| 6649 | |||
| 6650 | /// Returns a mutable pointer to the resolved error set type of an inferred | ||
| 6651 | /// error set function. The returned pointer is invalidated when anything is | ||
| 6652 | /// added to `ip`. | ||
| 6653 | pub fn funcIesResolved(ip: *const InternPool, func_index: InternPool.Index) *InternPool.Index { | ||
| 6654 | const tags = ip.items.items(.tag); | ||
| 6655 | const datas = ip.items.items(.data); | ||
| 6656 | assert(funcHasInferredErrorSet(ip, func_index)); | ||
| 6657 | const func_start = datas[@intFromEnum(func_index)]; | ||
| 6658 | const extra_index = switch (tags[@intFromEnum(func_index)]) { | ||
| 6659 | .func_decl => func_start + @typeInfo(Tag.FuncDecl).Struct.fields.len, | ||
| 6660 | .func_instance => func_start + @typeInfo(Tag.FuncInstance).Struct.fields.len, | ||
| 6661 | else => unreachable, | ||
| 6662 | }; | ||
| 6663 | return @ptrCast(&ip.extra.items[extra_index]); | ||
| 6664 | } |
src/Module.zig+18-126| ... | @@ -1297,98 +1297,6 @@ pub const Union = struct { | ... | @@ -1297,98 +1297,6 @@ pub const Union = struct { |
| 1297 | } | 1297 | } |
| 1298 | }; | 1298 | }; |
| 1299 | 1299 | ||
| 1300 | /// Some extern function struct memory is owned by the Decl's TypedValue.Managed | ||
| 1301 | /// arena allocator. | ||
| 1302 | pub const ExternFn = struct { | ||
| 1303 | /// The Decl that corresponds to the function itself. | ||
| 1304 | owner_decl: Decl.Index, | ||
| 1305 | /// Library name if specified. | ||
| 1306 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. | ||
| 1307 | /// Allocated with Module's allocator; outlives the ZIR code. | ||
| 1308 | lib_name: ?[*:0]const u8, | ||
| 1309 | |||
| 1310 | pub fn deinit(extern_fn: *ExternFn, gpa: Allocator) void { | ||
| 1311 | if (extern_fn.lib_name) |lib_name| { | ||
| 1312 | gpa.free(mem.sliceTo(lib_name, 0)); | ||
| 1313 | } | ||
| 1314 | } | ||
| 1315 | }; | ||
| 1316 | |||
| 1317 | /// This struct is used to keep track of any dependencies related to functions instances | ||
| 1318 | /// that return inferred error sets. Note that a function may be associated to | ||
| 1319 | /// multiple different error sets, for example an inferred error set which | ||
| 1320 | /// this function returns, but also any inferred error sets of called inline | ||
| 1321 | /// or comptime functions. | ||
| 1322 | pub const InferredErrorSet = struct { | ||
| 1323 | /// The function from which this error set originates. | ||
| 1324 | func: InternPool.Index, | ||
| 1325 | |||
| 1326 | /// All currently known errors that this error set contains. This includes | ||
| 1327 | /// direct additions via `return error.Foo;`, and possibly also errors that | ||
| 1328 | /// are returned from any dependent functions. When the inferred error set is | ||
| 1329 | /// fully resolved, this map contains all the errors that the function might return. | ||
| 1330 | errors: NameMap = .{}, | ||
| 1331 | |||
| 1332 | /// Other inferred error sets which this inferred error set should include. | ||
| 1333 | inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{}, | ||
| 1334 | |||
| 1335 | /// Whether the function returned anyerror. This is true if either of | ||
| 1336 | /// the dependent functions returns anyerror. | ||
| 1337 | is_anyerror: bool = false, | ||
| 1338 | |||
| 1339 | /// Whether this error set is already fully resolved. If true, resolving | ||
| 1340 | /// can skip resolving any dependents of this inferred error set. | ||
| 1341 | is_resolved: bool = false, | ||
| 1342 | |||
| 1343 | pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void); | ||
| 1344 | |||
| 1345 | pub const Index = enum(u32) { | ||
| 1346 | _, | ||
| 1347 | |||
| 1348 | pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex { | ||
| 1349 | return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(i))); | ||
| 1350 | } | ||
| 1351 | }; | ||
| 1352 | |||
| 1353 | pub const OptionalIndex = enum(u32) { | ||
| 1354 | none = std.math.maxInt(u32), | ||
| 1355 | _, | ||
| 1356 | |||
| 1357 | pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex { | ||
| 1358 | return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none))); | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index { | ||
| 1362 | if (oi == .none) return null; | ||
| 1363 | return @as(InferredErrorSet.Index, @enumFromInt(@intFromEnum(oi))); | ||
| 1364 | } | ||
| 1365 | }; | ||
| 1366 | |||
| 1367 | pub fn addErrorSet( | ||
| 1368 | self: *InferredErrorSet, | ||
| 1369 | err_set_ty: Type, | ||
| 1370 | ip: *InternPool, | ||
| 1371 | gpa: Allocator, | ||
| 1372 | ) !void { | ||
| 1373 | switch (err_set_ty.toIntern()) { | ||
| 1374 | .anyerror_type => { | ||
| 1375 | self.is_anyerror = true; | ||
| 1376 | }, | ||
| 1377 | else => switch (ip.indexToKey(err_set_ty.toIntern())) { | ||
| 1378 | .error_set_type => |error_set_type| { | ||
| 1379 | for (error_set_type.names) |name| { | ||
| 1380 | try self.errors.put(gpa, name, {}); | ||
| 1381 | } | ||
| 1382 | }, | ||
| 1383 | .inferred_error_set_type => |ies_index| { | ||
| 1384 | try self.inferred_error_sets.put(gpa, ies_index, {}); | ||
| 1385 | }, | ||
| 1386 | else => unreachable, | ||
| 1387 | }, | ||
| 1388 | } | ||
| 1389 | } | ||
| 1390 | }; | ||
| 1391 | |||
| 1392 | pub const DeclAdapter = struct { | 1300 | pub const DeclAdapter = struct { |
| 1393 | mod: *Module, | 1301 | mod: *Module, |
| 1394 | 1302 | ||
| ... | @@ -3220,10 +3128,6 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct { | ... | @@ -3220,10 +3128,6 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct { |
| 3220 | return mod.intern_pool.structPtr(index); | 3128 | return mod.intern_pool.structPtr(index); |
| 3221 | } | 3129 | } |
| 3222 | 3130 | ||
| 3223 | pub fn inferredErrorSetPtr(mod: *Module, index: InferredErrorSet.Index) *InferredErrorSet { | ||
| 3224 | return mod.intern_pool.inferredErrorSetPtr(index); | ||
| 3225 | } | ||
| 3226 | |||
| 3227 | pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace { | 3131 | pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace { |
| 3228 | return mod.namespacePtr(index.unwrap() orelse return null); | 3132 | return mod.namespacePtr(index.unwrap() orelse return null); |
| 3229 | } | 3133 | } |
| ... | @@ -4261,6 +4165,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { | ... | @@ -4261,6 +4165,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { |
| 4261 | .owner_decl_index = new_decl_index, | 4165 | .owner_decl_index = new_decl_index, |
| 4262 | .func_index = .none, | 4166 | .func_index = .none, |
| 4263 | .fn_ret_ty = Type.void, | 4167 | .fn_ret_ty = Type.void, |
| 4168 | .fn_ret_ty_ies = null, | ||
| 4264 | .owner_func_index = .none, | 4169 | .owner_func_index = .none, |
| 4265 | .comptime_mutable_decls = &comptime_mutable_decls, | 4170 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 4266 | }; | 4171 | }; |
| ... | @@ -4342,6 +4247,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4342,6 +4247,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4342 | .owner_decl_index = decl_index, | 4247 | .owner_decl_index = decl_index, |
| 4343 | .func_index = .none, | 4248 | .func_index = .none, |
| 4344 | .fn_ret_ty = Type.void, | 4249 | .fn_ret_ty = Type.void, |
| 4250 | .fn_ret_ty_ies = null, | ||
| 4345 | .owner_func_index = .none, | 4251 | .owner_func_index = .none, |
| 4346 | .comptime_mutable_decls = &comptime_mutable_decls, | 4252 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 4347 | }; | 4253 | }; |
| ... | @@ -5289,12 +5195,19 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -5289,12 +5195,19 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 5289 | .owner_decl_index = decl_index, | 5195 | .owner_decl_index = decl_index, |
| 5290 | .func_index = func_index, | 5196 | .func_index = func_index, |
| 5291 | .fn_ret_ty = fn_ty_info.return_type.toType(), | 5197 | .fn_ret_ty = fn_ty_info.return_type.toType(), |
| 5198 | .fn_ret_ty_ies = null, | ||
| 5292 | .owner_func_index = func_index, | 5199 | .owner_func_index = func_index, |
| 5293 | .branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota), | 5200 | .branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota), |
| 5294 | .comptime_mutable_decls = &comptime_mutable_decls, | 5201 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 5295 | }; | 5202 | }; |
| 5296 | defer sema.deinit(); | 5203 | defer sema.deinit(); |
| 5297 | 5204 | ||
| 5205 | if (func.analysis(ip).inferred_error_set) { | ||
| 5206 | const ies = try arena.create(Sema.InferredErrorSet); | ||
| 5207 | ies.* = .{ .func = func_index }; | ||
| 5208 | sema.fn_ret_ty_ies = ies; | ||
| 5209 | } | ||
| 5210 | |||
| 5298 | // reset in case calls to errorable functions are removed. | 5211 | // reset in case calls to errorable functions are removed. |
| 5299 | func.analysis(ip).calls_or_awaits_errorable_fn = false; | 5212 | func.analysis(ip).calls_or_awaits_errorable_fn = false; |
| 5300 | 5213 | ||
| ... | @@ -5433,7 +5346,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -5433,7 +5346,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 5433 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + | 5346 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 5434 | inner_block.instructions.items.len); | 5347 | inner_block.instructions.items.len); |
| 5435 | const main_block_index = sema.addExtraAssumeCapacity(Air.Block{ | 5348 | const main_block_index = sema.addExtraAssumeCapacity(Air.Block{ |
| 5436 | .body_len = @as(u32, @intCast(inner_block.instructions.items.len)), | 5349 | .body_len = @intCast(inner_block.instructions.items.len), |
| 5437 | }); | 5350 | }); |
| 5438 | sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items); | 5351 | sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items); |
| 5439 | sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index; | 5352 | sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index; |
| ... | @@ -5445,7 +5358,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -5445,7 +5358,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 5445 | // Crucially, this happens *after* we set the function state to success above, | 5358 | // Crucially, this happens *after* we set the function state to success above, |
| 5446 | // so that dependencies on the function body will now be satisfied rather than | 5359 | // so that dependencies on the function body will now be satisfied rather than |
| 5447 | // result in circular dependency errors. | 5360 | // result in circular dependency errors. |
| 5448 | sema.resolveFnTypes(fn_ty) catch |err| switch (err) { | 5361 | sema.resolveFnTypes(&inner_block, LazySrcLoc.nodeOffset(0), fn_ty) catch |err| switch (err) { |
| 5449 | error.NeededSourceLocation => unreachable, | 5362 | error.NeededSourceLocation => unreachable, |
| 5450 | error.GenericPoison => unreachable, | 5363 | error.GenericPoison => unreachable, |
| 5451 | error.ComptimeReturn => unreachable, | 5364 | error.ComptimeReturn => unreachable, |
| ... | @@ -6595,7 +6508,8 @@ pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Alloca | ... | @@ -6595,7 +6508,8 @@ pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Alloca |
| 6595 | 6508 | ||
| 6596 | pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type { | 6509 | pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type { |
| 6597 | const names: *const [1]InternPool.NullTerminatedString = &name; | 6510 | const names: *const [1]InternPool.NullTerminatedString = &name; |
| 6598 | return (try mod.intern_pool.get(mod.gpa, .{ .error_set_type = .{ .names = names } })).toType(); | 6511 | const new_ty = try mod.intern_pool.getErrorSetType(mod.gpa, names); |
| 6512 | return new_ty.toType(); | ||
| 6599 | } | 6513 | } |
| 6600 | 6514 | ||
| 6601 | /// Sorts `names` in place. | 6515 | /// Sorts `names` in place. |
| ... | @@ -6609,7 +6523,7 @@ pub fn errorSetFromUnsortedNames( | ... | @@ -6609,7 +6523,7 @@ pub fn errorSetFromUnsortedNames( |
| 6609 | {}, | 6523 | {}, |
| 6610 | InternPool.NullTerminatedString.indexLessThan, | 6524 | InternPool.NullTerminatedString.indexLessThan, |
| 6611 | ); | 6525 | ); |
| 6612 | const new_ty = try mod.intern(.{ .error_set_type = .{ .names = names } }); | 6526 | const new_ty = try mod.intern_pool.getErrorSetType(mod.gpa, names); |
| 6613 | return new_ty.toType(); | 6527 | return new_ty.toType(); |
| 6614 | } | 6528 | } |
| 6615 | 6529 | ||
| ... | @@ -6956,16 +6870,6 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType { | ... | @@ -6956,16 +6870,6 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType { |
| 6956 | return mod.intern_pool.indexToFuncType(ty.toIntern()); | 6870 | return mod.intern_pool.indexToFuncType(ty.toIntern()); |
| 6957 | } | 6871 | } |
| 6958 | 6872 | ||
| 6959 | pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*InferredErrorSet { | ||
| 6960 | const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null; | ||
| 6961 | return mod.inferredErrorSetPtr(index); | ||
| 6962 | } | ||
| 6963 | |||
| 6964 | pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) InferredErrorSet.OptionalIndex { | ||
| 6965 | if (ty.ip_index == .none) return .none; | ||
| 6966 | return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern()); | ||
| 6967 | } | ||
| 6968 | |||
| 6969 | pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl { | 6873 | pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl { |
| 6970 | return mod.declPtr(mod.funcOwnerDeclIndex(func_index)); | 6874 | return mod.declPtr(mod.funcOwnerDeclIndex(func_index)); |
| 6971 | } | 6875 | } |
| ... | @@ -6974,6 +6878,10 @@ pub fn funcOwnerDeclIndex(mod: *Module, func_index: InternPool.Index) Decl.Index | ... | @@ -6974,6 +6878,10 @@ pub fn funcOwnerDeclIndex(mod: *Module, func_index: InternPool.Index) Decl.Index |
| 6974 | return mod.funcInfo(func_index).owner_decl; | 6878 | return mod.funcInfo(func_index).owner_decl; |
| 6975 | } | 6879 | } |
| 6976 | 6880 | ||
| 6881 | pub fn iesFuncIndex(mod: *const Module, ies_index: InternPool.Index) InternPool.Index { | ||
| 6882 | return mod.intern_pool.iesFuncIndex(ies_index); | ||
| 6883 | } | ||
| 6884 | |||
| 6977 | pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func { | 6885 | pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func { |
| 6978 | return mod.intern_pool.indexToKey(func_index).func; | 6886 | return mod.intern_pool.indexToKey(func_index).func; |
| 6979 | } | 6887 | } |
| ... | @@ -7040,19 +6948,3 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0] | ... | @@ -7040,19 +6948,3 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0] |
| 7040 | else => unreachable, | 6948 | else => unreachable, |
| 7041 | }; | 6949 | }; |
| 7042 | } | 6950 | } |
| 7043 | |||
| 7044 | pub fn hasInferredErrorSet(mod: *Module, func: InternPool.Key.Func) bool { | ||
| 7045 | const owner_decl = mod.declPtr(func.owner_decl); | ||
| 7046 | const zir = owner_decl.getFileScope(mod).zir; | ||
| 7047 | const zir_tags = zir.instructions.items(.tag); | ||
| 7048 | switch (zir_tags[func.zir_body_inst]) { | ||
| 7049 | .func => return false, | ||
| 7050 | .func_inferred => return true, | ||
| 7051 | .func_fancy => { | ||
| 7052 | const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node; | ||
| 7053 | const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); | ||
| 7054 | return extra.data.bits.is_inferred_error; | ||
| 7055 | }, | ||
| 7056 | else => unreachable, | ||
| 7057 | } | ||
| 7058 | } |
src/Sema.zig+435-324| ... | @@ -38,6 +38,10 @@ error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, | ... | @@ -38,6 +38,10 @@ error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, |
| 38 | /// generic function which uses a type expression for the return type. | 38 | /// generic function which uses a type expression for the return type. |
| 39 | /// The type will be `void` in the case that `func` is `null`. | 39 | /// The type will be `void` in the case that `func` is `null`. |
| 40 | fn_ret_ty: Type, | 40 | fn_ret_ty: Type, |
| 41 | /// In case of the return type being an error union with an inferred error | ||
| 42 | /// set, this is the inferred error set. `null` otherwise. Allocated with | ||
| 43 | /// `Sema.arena`. | ||
| 44 | fn_ret_ty_ies: ?*InferredErrorSet, | ||
| 41 | branch_quota: u32 = default_branch_quota, | 45 | branch_quota: u32 = default_branch_quota, |
| 42 | branch_count: u32 = 0, | 46 | branch_count: u32 = 0, |
| 43 | /// Populated when returning `error.ComptimeBreak`. Used to communicate the | 47 | /// Populated when returning `error.ComptimeBreak`. Used to communicate the |
| ... | @@ -128,6 +132,46 @@ const Alignment = InternPool.Alignment; | ... | @@ -128,6 +132,46 @@ const Alignment = InternPool.Alignment; |
| 128 | pub const default_branch_quota = 1000; | 132 | pub const default_branch_quota = 1000; |
| 129 | pub const default_reference_trace_len = 2; | 133 | pub const default_reference_trace_len = 2; |
| 130 | 134 | ||
| 135 | pub const InferredErrorSet = struct { | ||
| 136 | /// The function body from which this error set originates. | ||
| 137 | func: InternPool.Index, | ||
| 138 | |||
| 139 | /// All currently known errors that this error set contains. This includes | ||
| 140 | /// direct additions via `return error.Foo;`, and possibly also errors that | ||
| 141 | /// are returned from any dependent functions. When the inferred error set is | ||
| 142 | /// fully resolved, this map contains all the errors that the function might return. | ||
| 143 | errors: NameMap = .{}, | ||
| 144 | |||
| 145 | /// Other inferred error sets which this inferred error set should include. | ||
| 146 | inferred_error_sets: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}, | ||
| 147 | |||
| 148 | pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void); | ||
| 149 | |||
| 150 | pub fn addErrorSet( | ||
| 151 | self: *InferredErrorSet, | ||
| 152 | err_set_ty: Type, | ||
| 153 | ip: *InternPool, | ||
| 154 | arena: Allocator, | ||
| 155 | ) !void { | ||
| 156 | switch (err_set_ty.toIntern()) { | ||
| 157 | .anyerror_type => { | ||
| 158 | ip.funcIesResolved(self.func).* = .anyerror_type; | ||
| 159 | }, | ||
| 160 | else => switch (ip.indexToKey(err_set_ty.toIntern())) { | ||
| 161 | .error_set_type => |error_set_type| { | ||
| 162 | for (error_set_type.names.get(ip)) |name| { | ||
| 163 | try self.errors.put(arena, name, {}); | ||
| 164 | } | ||
| 165 | }, | ||
| 166 | .inferred_error_set_type => { | ||
| 167 | try self.inferred_error_sets.put(arena, err_set_ty.toIntern(), {}); | ||
| 168 | }, | ||
| 169 | else => unreachable, | ||
| 170 | }, | ||
| 171 | } | ||
| 172 | } | ||
| 173 | }; | ||
| 174 | |||
| 131 | /// Stores the mapping from `Zir.Inst.Index -> Air.Inst.Ref`, which is used by sema to resolve | 175 | /// Stores the mapping from `Zir.Inst.Index -> Air.Inst.Ref`, which is used by sema to resolve |
| 132 | /// instructions during analysis. | 176 | /// instructions during analysis. |
| 133 | /// Instead of a hash table approach, InstMap is simply a slice that is indexed into using the | 177 | /// Instead of a hash table approach, InstMap is simply a slice that is indexed into using the |
| ... | @@ -1120,7 +1164,7 @@ fn analyzeBodyInner( | ... | @@ -1120,7 +1164,7 @@ fn analyzeBodyInner( |
| 1120 | .shl_sat => try sema.zirShl(block, inst, .shl_sat), | 1164 | .shl_sat => try sema.zirShl(block, inst, .shl_sat), |
| 1121 | 1165 | ||
| 1122 | .ret_ptr => try sema.zirRetPtr(block), | 1166 | .ret_ptr => try sema.zirRetPtr(block), |
| 1123 | .ret_type => try sema.addType(sema.fn_ret_ty), | 1167 | .ret_type => Air.internedToRef(sema.fn_ret_ty.toIntern()), |
| 1124 | 1168 | ||
| 1125 | // Instructions that we know to *always* be noreturn based solely on their tag. | 1169 | // Instructions that we know to *always* be noreturn based solely on their tag. |
| 1126 | // These functions match the return type of analyzeBody so that we can | 1170 | // These functions match the return type of analyzeBody so that we can |
| ... | @@ -3392,7 +3436,7 @@ fn zirErrorSetDecl( | ... | @@ -3392,7 +3436,7 @@ fn zirErrorSetDecl( |
| 3392 | const src = inst_data.src(); | 3436 | const src = inst_data.src(); |
| 3393 | const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); | 3437 | const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); |
| 3394 | 3438 | ||
| 3395 | var names: Module.InferredErrorSet.NameMap = .{}; | 3439 | var names: InferredErrorSet.NameMap = .{}; |
| 3396 | try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len); | 3440 | try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len); |
| 3397 | 3441 | ||
| 3398 | var extra_index = @as(u32, @intCast(extra.end)); | 3442 | var extra_index = @as(u32, @intCast(extra.end)); |
| ... | @@ -6933,12 +6977,10 @@ fn analyzeCall( | ... | @@ -6933,12 +6977,10 @@ fn analyzeCall( |
| 6933 | .return_type = owner_info.return_type, | 6977 | .return_type = owner_info.return_type, |
| 6934 | .comptime_bits = 0, | 6978 | .comptime_bits = 0, |
| 6935 | .noalias_bits = owner_info.noalias_bits, | 6979 | .noalias_bits = owner_info.noalias_bits, |
| 6936 | .alignment = owner_info.alignment, | 6980 | .alignment = if (owner_info.align_is_generic) null else owner_info.alignment, |
| 6937 | .cc = owner_info.cc, | 6981 | .cc = if (owner_info.cc_is_generic) null else owner_info.cc, |
| 6938 | .is_var_args = owner_info.is_var_args, | 6982 | .is_var_args = owner_info.is_var_args, |
| 6939 | .is_noinline = owner_info.is_noinline, | 6983 | .is_noinline = owner_info.is_noinline, |
| 6940 | .align_is_generic = owner_info.align_is_generic, | ||
| 6941 | .cc_is_generic = owner_info.cc_is_generic, | ||
| 6942 | .section_is_generic = owner_info.section_is_generic, | 6984 | .section_is_generic = owner_info.section_is_generic, |
| 6943 | .addrspace_is_generic = owner_info.addrspace_is_generic, | 6985 | .addrspace_is_generic = owner_info.addrspace_is_generic, |
| 6944 | .is_generic = owner_info.is_generic, | 6986 | .is_generic = owner_info.is_generic, |
| ... | @@ -7001,21 +7043,25 @@ fn analyzeCall( | ... | @@ -7001,21 +7043,25 @@ fn analyzeCall( |
| 7001 | try sema.resolveInst(fn_info.ret_ty_ref); | 7043 | try sema.resolveInst(fn_info.ret_ty_ref); |
| 7002 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; | 7044 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; |
| 7003 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); | 7045 | const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst); |
| 7004 | // Create a fresh inferred error set type for inline/comptime calls. | ||
| 7005 | const fn_ret_ty = blk: { | ||
| 7006 | if (mod.hasInferredErrorSet(module_fn)) { | ||
| 7007 | const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{ | ||
| 7008 | .func = module_fn_index, | ||
| 7009 | }); | ||
| 7010 | const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index }); | ||
| 7011 | break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type); | ||
| 7012 | } | ||
| 7013 | break :blk bare_return_type; | ||
| 7014 | }; | ||
| 7015 | new_fn_info.return_type = fn_ret_ty.toIntern(); | ||
| 7016 | const parent_fn_ret_ty = sema.fn_ret_ty; | 7046 | const parent_fn_ret_ty = sema.fn_ret_ty; |
| 7017 | sema.fn_ret_ty = fn_ret_ty; | 7047 | const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies; |
| 7048 | sema.fn_ret_ty = bare_return_type; | ||
| 7049 | sema.fn_ret_ty_ies = null; | ||
| 7018 | defer sema.fn_ret_ty = parent_fn_ret_ty; | 7050 | defer sema.fn_ret_ty = parent_fn_ret_ty; |
| 7051 | defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies; | ||
| 7052 | |||
| 7053 | if (module_fn.analysis(ip).inferred_error_set) { | ||
| 7054 | // Create a fresh inferred error set type for inline/comptime calls. | ||
| 7055 | const error_set_ty = try mod.intern(.{ .inferred_error_set_type = module_fn_index }); | ||
| 7056 | const ies = try sema.arena.create(InferredErrorSet); | ||
| 7057 | ies.* = .{ .func = module_fn_index }; | ||
| 7058 | sema.fn_ret_ty_ies = ies; | ||
| 7059 | sema.fn_ret_ty = (try ip.get(gpa, .{ .error_union_type = .{ | ||
| 7060 | .error_set_type = error_set_ty, | ||
| 7061 | .payload_type = bare_return_type.toIntern(), | ||
| 7062 | } })).toType(); | ||
| 7063 | ip.funcIesResolved(module_fn_index).* = .none; | ||
| 7064 | } | ||
| 7019 | 7065 | ||
| 7020 | // This `res2` is here instead of directly breaking from `res` due to a stage1 | 7066 | // This `res2` is here instead of directly breaking from `res` due to a stage1 |
| 7021 | // bug generating invalid LLVM IR. | 7067 | // bug generating invalid LLVM IR. |
| ... | @@ -7059,7 +7105,7 @@ fn analyzeCall( | ... | @@ -7059,7 +7105,7 @@ fn analyzeCall( |
| 7059 | } | 7105 | } |
| 7060 | 7106 | ||
| 7061 | if (is_comptime_call and ensure_result_used) { | 7107 | if (is_comptime_call and ensure_result_used) { |
| 7062 | try sema.ensureResultUsed(block, fn_ret_ty, call_src); | 7108 | try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); |
| 7063 | } | 7109 | } |
| 7064 | 7110 | ||
| 7065 | const result = result: { | 7111 | const result = result: { |
| ... | @@ -7089,7 +7135,7 @@ fn analyzeCall( | ... | @@ -7089,7 +7135,7 @@ fn analyzeCall( |
| 7089 | 7135 | ||
| 7090 | if (should_memoize and is_comptime_call) { | 7136 | if (should_memoize and is_comptime_call) { |
| 7091 | const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, ""); | 7137 | const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, ""); |
| 7092 | const result_interned = try result_val.intern(fn_ret_ty, mod); | 7138 | const result_interned = try result_val.intern(sema.fn_ret_ty, mod); |
| 7093 | 7139 | ||
| 7094 | // TODO: check whether any external comptime memory was mutated by the | 7140 | // TODO: check whether any external comptime memory was mutated by the |
| 7095 | // comptime function call. If so, then do not memoize the call here. | 7141 | // comptime function call. If so, then do not memoize the call here. |
| ... | @@ -7114,7 +7160,7 @@ fn analyzeCall( | ... | @@ -7114,7 +7160,7 @@ fn analyzeCall( |
| 7114 | if (i < fn_params_len) { | 7160 | if (i < fn_params_len) { |
| 7115 | const opts: CoerceOpts = .{ .param_src = .{ | 7161 | const opts: CoerceOpts = .{ .param_src = .{ |
| 7116 | .func_inst = func, | 7162 | .func_inst = func, |
| 7117 | .param_i = @as(u32, @intCast(i)), | 7163 | .param_i = @intCast(i), |
| 7118 | } }; | 7164 | } }; |
| 7119 | const param_ty = func_ty_info.param_types.get(ip)[i].toType(); | 7165 | const param_ty = func_ty_info.param_types.get(ip)[i].toType(); |
| 7120 | args[i] = sema.analyzeCallArg( | 7166 | args[i] = sema.analyzeCallArg( |
| ... | @@ -7433,6 +7479,7 @@ fn instantiateGenericCall( | ... | @@ -7433,6 +7479,7 @@ fn instantiateGenericCall( |
| 7433 | .owner_decl_index = sema.owner_decl_index, | 7479 | .owner_decl_index = sema.owner_decl_index, |
| 7434 | .func_index = sema.owner_func_index, | 7480 | .func_index = sema.owner_func_index, |
| 7435 | .fn_ret_ty = Type.void, | 7481 | .fn_ret_ty = Type.void, |
| 7482 | .fn_ret_ty_ies = null, | ||
| 7436 | .owner_func_index = .none, | 7483 | .owner_func_index = .none, |
| 7437 | .comptime_args = comptime_args, | 7484 | .comptime_args = comptime_args, |
| 7438 | .generic_owner = generic_owner, | 7485 | .generic_owner = generic_owner, |
| ... | @@ -7769,6 +7816,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -7769,6 +7816,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 7769 | defer tracy.end(); | 7816 | defer tracy.end(); |
| 7770 | 7817 | ||
| 7771 | const mod = sema.mod; | 7818 | const mod = sema.mod; |
| 7819 | const ip = &mod.intern_pool; | ||
| 7772 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 7820 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 7773 | const src = LazySrcLoc.nodeOffset(extra.node); | 7821 | const src = LazySrcLoc.nodeOffset(extra.node); |
| 7774 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; | 7822 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| ... | @@ -7779,7 +7827,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -7779,7 +7827,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 7779 | if (val.isUndef(mod)) { | 7827 | if (val.isUndef(mod)) { |
| 7780 | return sema.addConstUndef(Type.err_int); | 7828 | return sema.addConstUndef(Type.err_int); |
| 7781 | } | 7829 | } |
| 7782 | const err_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; | 7830 | const err_name = ip.indexToKey(val.toIntern()).err.name; |
| 7783 | return sema.addConstant(try mod.intValue( | 7831 | return sema.addConstant(try mod.intValue( |
| 7784 | Type.err_int, | 7832 | Type.err_int, |
| 7785 | try mod.getErrorValue(err_name), | 7833 | try mod.getErrorValue(err_name), |
| ... | @@ -7787,17 +7835,19 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD | ... | @@ -7787,17 +7835,19 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 7787 | } | 7835 | } |
| 7788 | 7836 | ||
| 7789 | const op_ty = sema.typeOf(uncasted_operand); | 7837 | const op_ty = sema.typeOf(uncasted_operand); |
| 7790 | try sema.resolveInferredErrorSetTy(block, src, op_ty); | 7838 | switch (try sema.resolveInferredErrorSetTy(block, src, op_ty.toIntern())) { |
| 7791 | if (!op_ty.isAnyError(mod)) { | 7839 | .anyerror_type => {}, |
| 7792 | const names = op_ty.errorSetNames(mod); | 7840 | else => |err_set_ty_index| { |
| 7793 | switch (names.len) { | 7841 | const names = ip.indexToKey(err_set_ty_index).error_set_type.names; |
| 7794 | 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)), | 7842 | switch (names.len) { |
| 7795 | 1 => { | 7843 | 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)), |
| 7796 | const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(names[0]).?)); | 7844 | 1 => { |
| 7797 | return sema.addIntUnsigned(Type.err_int, int); | 7845 | const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?); |
| 7798 | }, | 7846 | return sema.addIntUnsigned(Type.err_int, int); |
| 7799 | else => {}, | 7847 | }, |
| 7800 | } | 7848 | else => {}, |
| 7849 | } | ||
| 7850 | }, | ||
| 7801 | } | 7851 | } |
| 7802 | 7852 | ||
| 7803 | try sema.requireRuntimeBlock(block, src, operand_src); | 7853 | try sema.requireRuntimeBlock(block, src, operand_src); |
| ... | @@ -7846,6 +7896,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -7846,6 +7896,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 7846 | defer tracy.end(); | 7896 | defer tracy.end(); |
| 7847 | 7897 | ||
| 7848 | const mod = sema.mod; | 7898 | const mod = sema.mod; |
| 7899 | const ip = &mod.intern_pool; | ||
| 7849 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 7900 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 7850 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 7901 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 7851 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 7902 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| ... | @@ -7874,23 +7925,25 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -7874,23 +7925,25 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 7874 | return Air.Inst.Ref.anyerror_type; | 7925 | return Air.Inst.Ref.anyerror_type; |
| 7875 | } | 7926 | } |
| 7876 | 7927 | ||
| 7877 | if (mod.typeToInferredErrorSetIndex(lhs_ty).unwrap()) |ies_index| { | 7928 | if (ip.isInferredErrorSetType(lhs_ty.toIntern())) { |
| 7878 | try sema.resolveInferredErrorSet(block, src, ies_index); | 7929 | switch (try sema.resolveInferredErrorSet(block, src, lhs_ty.toIntern())) { |
| 7879 | // isAnyError might have changed from a false negative to a true positive after resolution. | 7930 | // isAnyError might have changed from a false negative to a true |
| 7880 | if (lhs_ty.isAnyError(mod)) { | 7931 | // positive after resolution. |
| 7881 | return Air.Inst.Ref.anyerror_type; | 7932 | .anyerror_type => return .anyerror_type, |
| 7933 | else => {}, | ||
| 7882 | } | 7934 | } |
| 7883 | } | 7935 | } |
| 7884 | if (mod.typeToInferredErrorSetIndex(rhs_ty).unwrap()) |ies_index| { | 7936 | if (ip.isInferredErrorSetType(rhs_ty.toIntern())) { |
| 7885 | try sema.resolveInferredErrorSet(block, src, ies_index); | 7937 | switch (try sema.resolveInferredErrorSet(block, src, rhs_ty.toIntern())) { |
| 7886 | // isAnyError might have changed from a false negative to a true positive after resolution. | 7938 | // isAnyError might have changed from a false negative to a true |
| 7887 | if (rhs_ty.isAnyError(mod)) { | 7939 | // positive after resolution. |
| 7888 | return Air.Inst.Ref.anyerror_type; | 7940 | .anyerror_type => return .anyerror_type, |
| 7941 | else => {}, | ||
| 7889 | } | 7942 | } |
| 7890 | } | 7943 | } |
| 7891 | 7944 | ||
| 7892 | const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty); | 7945 | const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty); |
| 7893 | return sema.addType(err_set_ty); | 7946 | return Air.internedToRef(err_set_ty.toIntern()); |
| 7894 | } | 7947 | } |
| 7895 | 7948 | ||
| 7896 | fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 7949 | fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -8569,6 +8622,12 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: | ... | @@ -8569,6 +8622,12 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: |
| 8569 | } | 8622 | } |
| 8570 | } | 8623 | } |
| 8571 | 8624 | ||
| 8625 | const Section = union(enum) { | ||
| 8626 | generic, | ||
| 8627 | default, | ||
| 8628 | explicit: InternPool.NullTerminatedString, | ||
| 8629 | }; | ||
| 8630 | |||
| 8572 | fn funcCommon( | 8631 | fn funcCommon( |
| 8573 | sema: *Sema, | 8632 | sema: *Sema, |
| 8574 | block: *Block, | 8633 | block: *Block, |
| ... | @@ -8578,7 +8637,7 @@ fn funcCommon( | ... | @@ -8578,7 +8637,7 @@ fn funcCommon( |
| 8578 | alignment: ?Alignment, | 8637 | alignment: ?Alignment, |
| 8579 | /// null means generic poison | 8638 | /// null means generic poison |
| 8580 | address_space: ?std.builtin.AddressSpace, | 8639 | address_space: ?std.builtin.AddressSpace, |
| 8581 | section: InternPool.GetFuncDeclKey.Section, | 8640 | section: Section, |
| 8582 | /// null means generic poison | 8641 | /// null means generic poison |
| 8583 | cc: ?std.builtin.CallingConvention, | 8642 | cc: ?std.builtin.CallingConvention, |
| 8584 | /// this might be Type.generic_poison | 8643 | /// this might be Type.generic_poison |
| ... | @@ -8709,6 +8768,36 @@ fn funcCommon( | ... | @@ -8709,6 +8768,36 @@ fn funcCommon( |
| 8709 | const param_types = block.params.items(.ty); | 8768 | const param_types = block.params.items(.ty); |
| 8710 | 8769 | ||
| 8711 | const opt_func_index: InternPool.Index = i: { | 8770 | const opt_func_index: InternPool.Index = i: { |
| 8771 | if (!is_source_decl) { | ||
| 8772 | assert(has_body); | ||
| 8773 | assert(!is_generic); | ||
| 8774 | assert(comptime_bits == 0); | ||
| 8775 | assert(cc != null); | ||
| 8776 | assert(section != .generic); | ||
| 8777 | assert(address_space != null); | ||
| 8778 | assert(!var_args); | ||
| 8779 | break :i try ip.getFuncInstance(gpa, .{ | ||
| 8780 | .param_types = param_types, | ||
| 8781 | .noalias_bits = noalias_bits, | ||
| 8782 | .bare_return_type = bare_return_type.toIntern(), | ||
| 8783 | .cc = cc_resolved, | ||
| 8784 | .alignment = alignment.?, | ||
| 8785 | .is_noinline = is_noinline, | ||
| 8786 | .inferred_error_set = inferred_error_set, | ||
| 8787 | .generic_owner = sema.generic_owner, | ||
| 8788 | }); | ||
| 8789 | } | ||
| 8790 | |||
| 8791 | // extern_func and func_decl functions take ownership of `sema.owner_decl`. | ||
| 8792 | |||
| 8793 | sema.owner_decl.@"linksection" = switch (section) { | ||
| 8794 | .generic => .none, | ||
| 8795 | .default => .none, | ||
| 8796 | .explicit => |section_name| section_name.toOptional(), | ||
| 8797 | }; | ||
| 8798 | sema.owner_decl.alignment = alignment orelse .none; | ||
| 8799 | sema.owner_decl.@"addrspace" = address_space orelse .generic; | ||
| 8800 | |||
| 8712 | if (is_extern) { | 8801 | if (is_extern) { |
| 8713 | assert(comptime_bits == 0); | 8802 | assert(comptime_bits == 0); |
| 8714 | assert(cc != null); | 8803 | assert(cc != null); |
| ... | @@ -8734,26 +8823,19 @@ fn funcCommon( | ... | @@ -8734,26 +8823,19 @@ fn funcCommon( |
| 8734 | 8823 | ||
| 8735 | if (!has_body) break :i .none; | 8824 | if (!has_body) break :i .none; |
| 8736 | 8825 | ||
| 8737 | if (is_source_decl) { | 8826 | if (inferred_error_set) { |
| 8738 | if (inferred_error_set) | 8827 | try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); |
| 8739 | try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); | 8828 | break :i try ip.getFuncDeclIes(gpa, .{ |
| 8740 | 8829 | .owner_decl = sema.owner_decl_index, | |
| 8741 | const fn_owner_decl = if (sema.generic_owner != .none) | ||
| 8742 | mod.funcOwnerDeclIndex(sema.generic_owner) | ||
| 8743 | else | ||
| 8744 | sema.owner_decl_index; | ||
| 8745 | 8830 | ||
| 8746 | break :i try ip.getFuncDecl(gpa, .{ | ||
| 8747 | .fn_owner_decl = fn_owner_decl, | ||
| 8748 | .param_types = param_types, | 8831 | .param_types = param_types, |
| 8749 | .noalias_bits = noalias_bits, | 8832 | .noalias_bits = noalias_bits, |
| 8750 | .comptime_bits = comptime_bits, | 8833 | .comptime_bits = comptime_bits, |
| 8751 | .return_type = bare_return_type.toIntern(), | 8834 | .bare_return_type = bare_return_type.toIntern(), |
| 8752 | .inferred_error_set = inferred_error_set, | ||
| 8753 | .cc = cc, | 8835 | .cc = cc, |
| 8754 | .alignment = alignment, | 8836 | .alignment = alignment, |
| 8755 | .section = section, | 8837 | .section_is_generic = section == .generic, |
| 8756 | .address_space = address_space, | 8838 | .addrspace_is_generic = address_space == null, |
| 8757 | .is_var_args = var_args, | 8839 | .is_var_args = var_args, |
| 8758 | .is_generic = final_is_generic, | 8840 | .is_generic = final_is_generic, |
| 8759 | .is_noinline = is_noinline, | 8841 | .is_noinline = is_noinline, |
| ... | @@ -8766,22 +8848,30 @@ fn funcCommon( | ... | @@ -8766,22 +8848,30 @@ fn funcCommon( |
| 8766 | }); | 8848 | }); |
| 8767 | } | 8849 | } |
| 8768 | 8850 | ||
| 8769 | assert(!is_generic); | 8851 | const func_ty = try ip.getFuncType(gpa, .{ |
| 8770 | assert(comptime_bits == 0); | ||
| 8771 | assert(cc != null); | ||
| 8772 | assert(section != .generic); | ||
| 8773 | assert(address_space != null); | ||
| 8774 | assert(!var_args); | ||
| 8775 | |||
| 8776 | break :i try ip.getFuncInstance(gpa, .{ | ||
| 8777 | .param_types = param_types, | 8852 | .param_types = param_types, |
| 8778 | .noalias_bits = noalias_bits, | 8853 | .noalias_bits = noalias_bits, |
| 8854 | .comptime_bits = comptime_bits, | ||
| 8779 | .return_type = bare_return_type.toIntern(), | 8855 | .return_type = bare_return_type.toIntern(), |
| 8780 | .cc = cc_resolved, | 8856 | .cc = cc, |
| 8781 | .alignment = alignment.?, | 8857 | .alignment = alignment, |
| 8858 | .section_is_generic = section == .generic, | ||
| 8859 | .addrspace_is_generic = address_space == null, | ||
| 8860 | .is_var_args = var_args, | ||
| 8861 | .is_generic = final_is_generic, | ||
| 8782 | .is_noinline = is_noinline, | 8862 | .is_noinline = is_noinline, |
| 8863 | }); | ||
| 8783 | 8864 | ||
| 8784 | .generic_owner = sema.generic_owner, | 8865 | break :i try ip.getFuncDecl(gpa, .{ |
| 8866 | .owner_decl = sema.owner_decl_index, | ||
| 8867 | .ty = func_ty, | ||
| 8868 | .cc = cc, | ||
| 8869 | .is_noinline = is_noinline, | ||
| 8870 | .zir_body_inst = func_inst, | ||
| 8871 | .lbrace_line = src_locs.lbrace_line, | ||
| 8872 | .rbrace_line = src_locs.rbrace_line, | ||
| 8873 | .lbrace_column = @as(u16, @truncate(src_locs.columns)), | ||
| 8874 | .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), | ||
| 8785 | }); | 8875 | }); |
| 8786 | }; | 8876 | }; |
| 8787 | 8877 | ||
| ... | @@ -8913,10 +9003,8 @@ fn funcCommon( | ... | @@ -8913,10 +9003,8 @@ fn funcCommon( |
| 8913 | .noalias_bits = noalias_bits, | 9003 | .noalias_bits = noalias_bits, |
| 8914 | .comptime_bits = comptime_bits, | 9004 | .comptime_bits = comptime_bits, |
| 8915 | .return_type = return_type.toIntern(), | 9005 | .return_type = return_type.toIntern(), |
| 8916 | .cc = cc_resolved, | 9006 | .cc = cc, |
| 8917 | .cc_is_generic = cc == null, | 9007 | .alignment = alignment, |
| 8918 | .alignment = alignment orelse .none, | ||
| 8919 | .align_is_generic = alignment == null, | ||
| 8920 | .section_is_generic = section == .generic, | 9008 | .section_is_generic = section == .generic, |
| 8921 | .addrspace_is_generic = address_space == null, | 9009 | .addrspace_is_generic = address_space == null, |
| 8922 | .is_var_args = var_args, | 9010 | .is_var_args = var_args, |
| ... | @@ -10254,7 +10342,7 @@ const SwitchProngAnalysis = struct { | ... | @@ -10254,7 +10342,7 @@ const SwitchProngAnalysis = struct { |
| 10254 | return sema.bitCast(block, item_ty, spa.operand, operand_src, null); | 10342 | return sema.bitCast(block, item_ty, spa.operand, operand_src, null); |
| 10255 | } | 10343 | } |
| 10256 | 10344 | ||
| 10257 | var names: Module.InferredErrorSet.NameMap = .{}; | 10345 | var names: InferredErrorSet.NameMap = .{}; |
| 10258 | try names.ensureUnusedCapacity(sema.arena, case_vals.len); | 10346 | try names.ensureUnusedCapacity(sema.arena, case_vals.len); |
| 10259 | for (case_vals) |err| { | 10347 | for (case_vals) |err| { |
| 10260 | const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable; | 10348 | const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable; |
| ... | @@ -10622,97 +10710,100 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r | ... | @@ -10622,97 +10710,100 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r |
| 10622 | } | 10710 | } |
| 10623 | } | 10711 | } |
| 10624 | 10712 | ||
| 10625 | try sema.resolveInferredErrorSetTy(block, src, operand_ty); | 10713 | switch (try sema.resolveInferredErrorSetTy(block, src, operand_ty.toIntern())) { |
| 10626 | 10714 | .anyerror_type => { | |
| 10627 | if (operand_ty.isAnyError(mod)) { | 10715 | if (special_prong != .@"else") { |
| 10628 | if (special_prong != .@"else") { | 10716 | return sema.fail( |
| 10629 | return sema.fail( | 10717 | block, |
| 10630 | block, | 10718 | src, |
| 10631 | src, | 10719 | "else prong required when switching on type 'anyerror'", |
| 10632 | "else prong required when switching on type 'anyerror'", | 10720 | .{}, |
| 10633 | .{}, | 10721 | ); |
| 10634 | ); | 10722 | } |
| 10635 | } | 10723 | else_error_ty = Type.anyerror; |
| 10636 | else_error_ty = Type.anyerror; | 10724 | }, |
| 10637 | } else else_validation: { | 10725 | else => |err_set_ty_index| else_validation: { |
| 10638 | var maybe_msg: ?*Module.ErrorMsg = null; | 10726 | const error_names = ip.indexToKey(err_set_ty_index).error_set_type.names; |
| 10639 | errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa); | 10727 | var maybe_msg: ?*Module.ErrorMsg = null; |
| 10728 | errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa); | ||
| 10729 | |||
| 10730 | for (error_names.get(ip)) |error_name| { | ||
| 10731 | if (!seen_errors.contains(error_name) and special_prong != .@"else") { | ||
| 10732 | const msg = maybe_msg orelse blk: { | ||
| 10733 | maybe_msg = try sema.errMsg( | ||
| 10734 | block, | ||
| 10735 | src, | ||
| 10736 | "switch must handle all possibilities", | ||
| 10737 | .{}, | ||
| 10738 | ); | ||
| 10739 | break :blk maybe_msg.?; | ||
| 10740 | }; | ||
| 10640 | 10741 | ||
| 10641 | for (operand_ty.errorSetNames(mod)) |error_name| { | 10742 | try sema.errNote( |
| 10642 | if (!seen_errors.contains(error_name) and special_prong != .@"else") { | ||
| 10643 | const msg = maybe_msg orelse blk: { | ||
| 10644 | maybe_msg = try sema.errMsg( | ||
| 10645 | block, | 10743 | block, |
| 10646 | src, | 10744 | src, |
| 10647 | "switch must handle all possibilities", | 10745 | msg, |
| 10648 | .{}, | 10746 | "unhandled error value: 'error.{}'", |
| 10747 | .{error_name.fmt(ip)}, | ||
| 10649 | ); | 10748 | ); |
| 10650 | break :blk maybe_msg.?; | 10749 | } |
| 10651 | }; | ||
| 10652 | |||
| 10653 | try sema.errNote( | ||
| 10654 | block, | ||
| 10655 | src, | ||
| 10656 | msg, | ||
| 10657 | "unhandled error value: 'error.{}'", | ||
| 10658 | .{error_name.fmt(ip)}, | ||
| 10659 | ); | ||
| 10660 | } | 10750 | } |
| 10661 | } | ||
| 10662 | 10751 | ||
| 10663 | if (maybe_msg) |msg| { | 10752 | if (maybe_msg) |msg| { |
| 10664 | maybe_msg = null; | 10753 | maybe_msg = null; |
| 10665 | try sema.addDeclaredHereNote(msg, operand_ty); | 10754 | try sema.addDeclaredHereNote(msg, operand_ty); |
| 10666 | return sema.failWithOwnedErrorMsg(msg); | 10755 | return sema.failWithOwnedErrorMsg(msg); |
| 10667 | } | 10756 | } |
| 10668 | 10757 | ||
| 10669 | if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames(mod).len) { | 10758 | if (special_prong == .@"else" and |
| 10670 | // In order to enable common patterns for generic code allow simple else bodies | 10759 | seen_errors.count() == error_names.len) |
| 10671 | // else => unreachable, | 10760 | { |
| 10672 | // else => return, | 10761 | // In order to enable common patterns for generic code allow simple else bodies |
| 10673 | // else => |e| return e, | 10762 | // else => unreachable, |
| 10674 | // even if all the possible errors were already handled. | 10763 | // else => return, |
| 10675 | const tags = sema.code.instructions.items(.tag); | 10764 | // else => |e| return e, |
| 10676 | for (special.body) |else_inst| switch (tags[else_inst]) { | 10765 | // even if all the possible errors were already handled. |
| 10677 | .dbg_block_begin, | 10766 | const tags = sema.code.instructions.items(.tag); |
| 10678 | .dbg_block_end, | 10767 | for (special.body) |else_inst| switch (tags[else_inst]) { |
| 10679 | .dbg_stmt, | 10768 | .dbg_block_begin, |
| 10680 | .dbg_var_val, | 10769 | .dbg_block_end, |
| 10681 | .ret_type, | 10770 | .dbg_stmt, |
| 10682 | .as_node, | 10771 | .dbg_var_val, |
| 10683 | .ret_node, | 10772 | .ret_type, |
| 10684 | .@"unreachable", | 10773 | .as_node, |
| 10685 | .@"defer", | 10774 | .ret_node, |
| 10686 | .defer_err_code, | 10775 | .@"unreachable", |
| 10687 | .err_union_code, | 10776 | .@"defer", |
| 10688 | .ret_err_value_code, | 10777 | .defer_err_code, |
| 10689 | .restore_err_ret_index, | 10778 | .err_union_code, |
| 10690 | .is_non_err, | 10779 | .ret_err_value_code, |
| 10691 | .ret_is_non_err, | 10780 | .restore_err_ret_index, |
| 10692 | .condbr, | 10781 | .is_non_err, |
| 10693 | => {}, | 10782 | .ret_is_non_err, |
| 10694 | else => break, | 10783 | .condbr, |
| 10695 | } else break :else_validation; | 10784 | => {}, |
| 10785 | else => break, | ||
| 10786 | } else break :else_validation; | ||
| 10696 | 10787 | ||
| 10697 | return sema.fail( | 10788 | return sema.fail( |
| 10698 | block, | 10789 | block, |
| 10699 | special_prong_src, | 10790 | special_prong_src, |
| 10700 | "unreachable else prong; all cases already handled", | 10791 | "unreachable else prong; all cases already handled", |
| 10701 | .{}, | 10792 | .{}, |
| 10702 | ); | 10793 | ); |
| 10703 | } | 10794 | } |
| 10704 | 10795 | ||
| 10705 | const error_names = operand_ty.errorSetNames(mod); | 10796 | var names: InferredErrorSet.NameMap = .{}; |
| 10706 | var names: Module.InferredErrorSet.NameMap = .{}; | 10797 | try names.ensureUnusedCapacity(sema.arena, error_names.len); |
| 10707 | try names.ensureUnusedCapacity(sema.arena, error_names.len); | 10798 | for (error_names.get(ip)) |error_name| { |
| 10708 | for (error_names) |error_name| { | 10799 | if (seen_errors.contains(error_name)) continue; |
| 10709 | if (seen_errors.contains(error_name)) continue; | ||
| 10710 | 10800 | ||
| 10711 | names.putAssumeCapacityNoClobber(error_name, {}); | 10801 | names.putAssumeCapacityNoClobber(error_name, {}); |
| 10712 | } | 10802 | } |
| 10713 | // No need to keep the hash map metadata correct; here we | 10803 | // No need to keep the hash map metadata correct; here we |
| 10714 | // extract the (sorted) keys only. | 10804 | // extract the (sorted) keys only. |
| 10715 | else_error_ty = try mod.errorSetFromUnsortedNames(names.keys()); | 10805 | else_error_ty = try mod.errorSetFromUnsortedNames(names.keys()); |
| 10806 | }, | ||
| 10716 | } | 10807 | } |
| 10717 | }, | 10808 | }, |
| 10718 | .Int, .ComptimeInt => { | 10809 | .Int, .ComptimeInt => { |
| ... | @@ -16444,50 +16535,51 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -16444,50 +16535,51 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16444 | 16535 | ||
| 16445 | try sema.queueFullTypeResolution(error_field_ty); | 16536 | try sema.queueFullTypeResolution(error_field_ty); |
| 16446 | 16537 | ||
| 16447 | // If the error set is inferred it must be resolved at this point | ||
| 16448 | try sema.resolveInferredErrorSetTy(block, src, ty); | ||
| 16449 | |||
| 16450 | // Build our list of Error values | 16538 | // Build our list of Error values |
| 16451 | // Optional value is only null if anyerror | 16539 | // Optional value is only null if anyerror |
| 16452 | // Value can be zero-length slice otherwise | 16540 | // Value can be zero-length slice otherwise |
| 16453 | const error_field_vals = if (ty.isAnyError(mod)) null else blk: { | 16541 | const error_field_vals = switch (try sema.resolveInferredErrorSetTy(block, src, ty.toIntern())) { |
| 16454 | const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len); | 16542 | .anyerror_type => null, |
| 16455 | for (vals, 0..) |*field_val, i| { | 16543 | else => |err_set_ty_index| blk: { |
| 16456 | // TODO: write something like getCoercedInts to avoid needing to dupe | 16544 | const names = ip.indexToKey(err_set_ty_index).error_set_type.names; |
| 16457 | const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i])); | 16545 | const vals = try sema.arena.alloc(InternPool.Index, names.len); |
| 16458 | const name_val = v: { | 16546 | for (vals, 0..) |*field_val, i| { |
| 16459 | var anon_decl = try block.startAnonDecl(); | 16547 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 16460 | defer anon_decl.deinit(); | 16548 | const name = try sema.arena.dupe(u8, ip.stringToSlice(names.get(ip)[i])); |
| 16461 | const new_decl_ty = try mod.arrayType(.{ | 16549 | const name_val = v: { |
| 16462 | .len = name.len, | 16550 | var anon_decl = try block.startAnonDecl(); |
| 16463 | .child = .u8_type, | 16551 | defer anon_decl.deinit(); |
| 16464 | }); | 16552 | const new_decl_ty = try mod.arrayType(.{ |
| 16465 | const new_decl = try anon_decl.finish( | 16553 | .len = name.len, |
| 16466 | new_decl_ty, | 16554 | .child = .u8_type, |
| 16467 | (try mod.intern(.{ .aggregate = .{ | 16555 | }); |
| 16468 | .ty = new_decl_ty.toIntern(), | 16556 | const new_decl = try anon_decl.finish( |
| 16469 | .storage = .{ .bytes = name }, | 16557 | new_decl_ty, |
| 16470 | } })).toValue(), | 16558 | (try mod.intern(.{ .aggregate = .{ |
| 16471 | .none, // default alignment | 16559 | .ty = new_decl_ty.toIntern(), |
| 16472 | ); | 16560 | .storage = .{ .bytes = name }, |
| 16473 | break :v try mod.intern(.{ .ptr = .{ | 16561 | } })).toValue(), |
| 16474 | .ty = .slice_const_u8_type, | 16562 | .none, // default alignment |
| 16475 | .addr = .{ .decl = new_decl }, | 16563 | ); |
| 16476 | .len = (try mod.intValue(Type.usize, name.len)).toIntern(), | 16564 | break :v try mod.intern(.{ .ptr = .{ |
| 16477 | } }); | 16565 | .ty = .slice_const_u8_type, |
| 16478 | }; | 16566 | .addr = .{ .decl = new_decl }, |
| 16567 | .len = (try mod.intValue(Type.usize, name.len)).toIntern(), | ||
| 16568 | } }); | ||
| 16569 | }; | ||
| 16479 | 16570 | ||
| 16480 | const error_field_fields = .{ | 16571 | const error_field_fields = .{ |
| 16481 | // name: []const u8, | 16572 | // name: []const u8, |
| 16482 | name_val, | 16573 | name_val, |
| 16483 | }; | 16574 | }; |
| 16484 | field_val.* = try mod.intern(.{ .aggregate = .{ | 16575 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 16485 | .ty = error_field_ty.toIntern(), | 16576 | .ty = error_field_ty.toIntern(), |
| 16486 | .storage = .{ .elems = &error_field_fields }, | 16577 | .storage = .{ .elems = &error_field_fields }, |
| 16487 | } }); | 16578 | } }); |
| 16488 | } | 16579 | } |
| 16489 | 16580 | ||
| 16490 | break :blk vals; | 16581 | break :blk vals; |
| 16582 | }, | ||
| 16491 | }; | 16583 | }; |
| 16492 | 16584 | ||
| 16493 | // Build our ?[]const Error value | 16585 | // Build our ?[]const Error value |
| ... | @@ -18055,7 +18147,9 @@ fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { | ... | @@ -18055,7 +18147,9 @@ fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void { |
| 18055 | const ip = &mod.intern_pool; | 18147 | const ip = &mod.intern_pool; |
| 18056 | assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion); | 18148 | assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion); |
| 18057 | 18149 | ||
| 18058 | if (mod.typeToInferredErrorSet(sema.fn_ret_ty.errorUnionSet(mod))) |ies| { | 18150 | if (ip.isInferredErrorSetType(sema.fn_ret_ty.errorUnionSet(mod).toIntern())) { |
| 18151 | const ies = sema.fn_ret_ty_ies.?; | ||
| 18152 | assert(ies.func == sema.func_index); | ||
| 18059 | const op_ty = sema.typeOf(uncasted_operand); | 18153 | const op_ty = sema.typeOf(uncasted_operand); |
| 18060 | switch (op_ty.zigTypeTag(mod)) { | 18154 | switch (op_ty.zigTypeTag(mod)) { |
| 18061 | .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa), | 18155 | .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa), |
| ... | @@ -19508,7 +19602,7 @@ fn zirReify( | ... | @@ -19508,7 +19602,7 @@ fn zirReify( |
| 19508 | return sema.addType(Type.anyerror); | 19602 | return sema.addType(Type.anyerror); |
| 19509 | 19603 | ||
| 19510 | const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod)); | 19604 | const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod)); |
| 19511 | var names: Module.InferredErrorSet.NameMap = .{}; | 19605 | var names: InferredErrorSet.NameMap = .{}; |
| 19512 | try names.ensureUnusedCapacity(sema.arena, len); | 19606 | try names.ensureUnusedCapacity(sema.arena, len); |
| 19513 | for (0..len) |i| { | 19607 | for (0..len) |i| { |
| 19514 | const elem_val = try payload_val.elemValue(mod, i); | 19608 | const elem_val = try payload_val.elemValue(mod, i); |
| ... | @@ -20019,8 +20113,6 @@ fn zirReify( | ... | @@ -20019,8 +20113,6 @@ fn zirReify( |
| 20019 | .is_var_args = is_var_args, | 20113 | .is_var_args = is_var_args, |
| 20020 | .is_generic = false, | 20114 | .is_generic = false, |
| 20021 | .is_noinline = false, | 20115 | .is_noinline = false, |
| 20022 | .align_is_generic = false, | ||
| 20023 | .cc_is_generic = false, | ||
| 20024 | .section_is_generic = false, | 20116 | .section_is_generic = false, |
| 20025 | .addrspace_is_generic = false, | 20117 | .addrspace_is_generic = false, |
| 20026 | }); | 20118 | }); |
| ... | @@ -20524,8 +20616,8 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat | ... | @@ -20524,8 +20616,8 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 20524 | break :disjoint true; | 20616 | break :disjoint true; |
| 20525 | } | 20617 | } |
| 20526 | 20618 | ||
| 20527 | try sema.resolveInferredErrorSetTy(block, src, dest_ty); | 20619 | _ = try sema.resolveInferredErrorSetTy(block, src, dest_ty.toIntern()); |
| 20528 | try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty); | 20620 | _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty.toIntern()); |
| 20529 | for (dest_ty.errorSetNames(mod)) |dest_err_name| { | 20621 | for (dest_ty.errorSetNames(mod)) |dest_err_name| { |
| 20530 | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) | 20622 | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) |
| 20531 | break :disjoint false; | 20623 | break :disjoint false; |
| ... | @@ -23505,7 +23597,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -23505,7 +23597,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 23505 | break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val); | 23597 | break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val); |
| 23506 | } else target_util.defaultAddressSpace(target, .function); | 23598 | } else target_util.defaultAddressSpace(target, .function); |
| 23507 | 23599 | ||
| 23508 | const section: InternPool.GetFuncDeclKey.Section = if (extra.data.bits.has_section_body) blk: { | 23600 | const section: Section = if (extra.data.bits.has_section_body) blk: { |
| 23509 | const body_len = sema.code.extra[extra_index]; | 23601 | const body_len = sema.code.extra[extra_index]; |
| 23510 | extra_index += 1; | 23602 | extra_index += 1; |
| 23511 | const body = sema.code.extra[extra_index..][0..body_len]; | 23603 | const body = sema.code.extra[extra_index..][0..body_len]; |
| ... | @@ -27750,42 +27842,22 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -27750,42 +27842,22 @@ fn coerceInMemoryAllowedErrorSets( |
| 27750 | return .ok; | 27842 | return .ok; |
| 27751 | } | 27843 | } |
| 27752 | 27844 | ||
| 27753 | if (mod.typeToInferredErrorSetIndex(dest_ty).unwrap()) |dst_ies_index| { | 27845 | if (ip.isInferredErrorSetType(dest_ty.toIntern())) { |
| 27754 | const dst_ies = mod.inferredErrorSetPtr(dst_ies_index); | 27846 | const dst_ies_func_index = ip.iesFuncIndex(dest_ty.toIntern()); |
| 27755 | // We will make an effort to return `ok` without resolving either error set, to | 27847 | if (sema.fn_ret_ty_ies) |dst_ies| { |
| 27756 | // avoid unnecessary "unable to resolve error set" dependency loop errors. | 27848 | if (dst_ies.func == dst_ies_func_index) { |
| 27757 | switch (src_ty.toIntern()) { | 27849 | // We are trying to coerce an error set to the current function's |
| 27758 | .anyerror_type => {}, | 27850 | // inferred error set. |
| 27759 | else => switch (ip.indexToKey(src_ty.toIntern())) { | 27851 | try dst_ies.addErrorSet(src_ty, ip, gpa); |
| 27760 | .inferred_error_set_type => |src_index| { | 27852 | return .ok; |
| 27761 | // If both are inferred error sets of functions, and | 27853 | } |
| 27762 | // the dest includes the source function, the coercion is OK. | ||
| 27763 | // This check is important because it works without forcing a full resolution | ||
| 27764 | // of inferred error sets. | ||
| 27765 | if (dst_ies.inferred_error_sets.contains(src_index)) { | ||
| 27766 | return .ok; | ||
| 27767 | } | ||
| 27768 | }, | ||
| 27769 | .error_set_type => |error_set_type| { | ||
| 27770 | for (error_set_type.names) |name| { | ||
| 27771 | if (!dst_ies.errors.contains(name)) break; | ||
| 27772 | } else return .ok; | ||
| 27773 | }, | ||
| 27774 | else => unreachable, | ||
| 27775 | }, | ||
| 27776 | } | ||
| 27777 | |||
| 27778 | if (dst_ies.func == sema.owner_func_index) { | ||
| 27779 | // We are trying to coerce an error set to the current function's | ||
| 27780 | // inferred error set. | ||
| 27781 | try dst_ies.addErrorSet(src_ty, ip, gpa); | ||
| 27782 | return .ok; | ||
| 27783 | } | 27854 | } |
| 27784 | 27855 | ||
| 27785 | try sema.resolveInferredErrorSet(block, dest_src, dst_ies_index); | 27856 | switch (try sema.resolveInferredErrorSet(block, dest_src, dest_ty.toIntern())) { |
| 27786 | // isAnyError might have changed from a false negative to a true positive after resolution. | 27857 | // isAnyError might have changed from a false negative to a true |
| 27787 | if (dest_ty.isAnyError(mod)) { | 27858 | // positive after resolution. |
| 27788 | return .ok; | 27859 | .anyerror_type => return .ok, |
| 27860 | else => {}, | ||
| 27789 | } | 27861 | } |
| 27790 | } | 27862 | } |
| 27791 | 27863 | ||
| ... | @@ -27800,17 +27872,15 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -27800,17 +27872,15 @@ fn coerceInMemoryAllowedErrorSets( |
| 27800 | }, | 27872 | }, |
| 27801 | 27873 | ||
| 27802 | else => switch (ip.indexToKey(src_ty.toIntern())) { | 27874 | else => switch (ip.indexToKey(src_ty.toIntern())) { |
| 27803 | .inferred_error_set_type => |src_index| { | 27875 | .inferred_error_set_type => { |
| 27804 | const src_data = mod.inferredErrorSetPtr(src_index); | 27876 | const resolved_src_ty = try sema.resolveInferredErrorSet(block, src_src, src_ty.toIntern()); |
| 27805 | |||
| 27806 | try sema.resolveInferredErrorSet(block, src_src, src_index); | ||
| 27807 | // src anyerror status might have changed after the resolution. | 27877 | // src anyerror status might have changed after the resolution. |
| 27808 | if (src_ty.isAnyError(mod)) { | 27878 | if (resolved_src_ty == .anyerror_type) { |
| 27809 | // dest_ty.isAnyError(mod) == true is already checked for at this point. | 27879 | // dest_ty.isAnyError(mod) == true is already checked for at this point. |
| 27810 | return .from_anyerror; | 27880 | return .from_anyerror; |
| 27811 | } | 27881 | } |
| 27812 | 27882 | ||
| 27813 | for (src_data.errors.keys()) |key| { | 27883 | for (ip.indexToKey(resolved_src_ty).error_set_type.names.get(ip)) |key| { |
| 27814 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) { | 27884 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) { |
| 27815 | try missing_error_buf.append(key); | 27885 | try missing_error_buf.append(key); |
| 27816 | } | 27886 | } |
| ... | @@ -27825,7 +27895,7 @@ fn coerceInMemoryAllowedErrorSets( | ... | @@ -27825,7 +27895,7 @@ fn coerceInMemoryAllowedErrorSets( |
| 27825 | return .ok; | 27895 | return .ok; |
| 27826 | }, | 27896 | }, |
| 27827 | .error_set_type => |error_set_type| { | 27897 | .error_set_type => |error_set_type| { |
| 27828 | for (error_set_type.names) |name| { | 27898 | for (error_set_type.names.get(ip)) |name| { |
| 27829 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) { | 27899 | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) { |
| 27830 | try missing_error_buf.append(name); | 27900 | try missing_error_buf.append(name); |
| 27831 | } | 27901 | } |
| ... | @@ -30341,73 +30411,72 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -30341,73 +30411,72 @@ fn analyzeIsNonErrComptimeOnly( |
| 30341 | operand: Air.Inst.Ref, | 30411 | operand: Air.Inst.Ref, |
| 30342 | ) CompileError!Air.Inst.Ref { | 30412 | ) CompileError!Air.Inst.Ref { |
| 30343 | const mod = sema.mod; | 30413 | const mod = sema.mod; |
| 30414 | const ip = &mod.intern_pool; | ||
| 30344 | const operand_ty = sema.typeOf(operand); | 30415 | const operand_ty = sema.typeOf(operand); |
| 30345 | const ot = operand_ty.zigTypeTag(mod); | 30416 | const ot = operand_ty.zigTypeTag(mod); |
| 30346 | if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true; | 30417 | if (ot != .ErrorSet and ot != .ErrorUnion) return .bool_true; |
| 30347 | if (ot == .ErrorSet) return Air.Inst.Ref.bool_false; | 30418 | if (ot == .ErrorSet) return .bool_false; |
| 30348 | assert(ot == .ErrorUnion); | 30419 | assert(ot == .ErrorUnion); |
| 30349 | 30420 | ||
| 30350 | const payload_ty = operand_ty.errorUnionPayload(mod); | 30421 | const payload_ty = operand_ty.errorUnionPayload(mod); |
| 30351 | if (payload_ty.zigTypeTag(mod) == .NoReturn) { | 30422 | if (payload_ty.zigTypeTag(mod) == .NoReturn) { |
| 30352 | return Air.Inst.Ref.bool_false; | 30423 | return .bool_false; |
| 30353 | } | 30424 | } |
| 30354 | 30425 | ||
| 30355 | if (Air.refToIndex(operand)) |operand_inst| { | 30426 | if (Air.refToIndex(operand)) |operand_inst| { |
| 30356 | switch (sema.air_instructions.items(.tag)[operand_inst]) { | 30427 | switch (sema.air_instructions.items(.tag)[operand_inst]) { |
| 30357 | .wrap_errunion_payload => return Air.Inst.Ref.bool_true, | 30428 | .wrap_errunion_payload => return .bool_true, |
| 30358 | .wrap_errunion_err => return Air.Inst.Ref.bool_false, | 30429 | .wrap_errunion_err => return .bool_false, |
| 30359 | else => {}, | 30430 | else => {}, |
| 30360 | } | 30431 | } |
| 30361 | } else if (operand == .undef) { | 30432 | } else if (operand == .undef) { |
| 30362 | return sema.addConstUndef(Type.bool); | 30433 | return sema.addConstUndef(Type.bool); |
| 30363 | } else if (@intFromEnum(operand) < InternPool.static_len) { | 30434 | } else if (@intFromEnum(operand) < InternPool.static_len) { |
| 30364 | // None of the ref tags can be errors. | 30435 | // None of the ref tags can be errors. |
| 30365 | return Air.Inst.Ref.bool_true; | 30436 | return .bool_true; |
| 30366 | } | 30437 | } |
| 30367 | 30438 | ||
| 30368 | const maybe_operand_val = try sema.resolveMaybeUndefVal(operand); | 30439 | const maybe_operand_val = try sema.resolveMaybeUndefVal(operand); |
| 30369 | 30440 | ||
| 30370 | // exception if the error union error set is known to be empty, | 30441 | // exception if the error union error set is known to be empty, |
| 30371 | // we allow the comparison but always make it comptime-known. | 30442 | // we allow the comparison but always make it comptime-known. |
| 30372 | const set_ty = operand_ty.errorUnionSet(mod); | 30443 | const set_ty = ip.errorUnionSet(operand_ty.toIntern()); |
| 30373 | switch (set_ty.toIntern()) { | 30444 | switch (set_ty) { |
| 30374 | .anyerror_type => {}, | 30445 | .anyerror_type => {}, |
| 30375 | else => switch (mod.intern_pool.indexToKey(set_ty.toIntern())) { | 30446 | else => switch (ip.indexToKey(set_ty)) { |
| 30376 | .error_set_type => |error_set_type| { | 30447 | .error_set_type => |error_set_type| { |
| 30377 | if (error_set_type.names.len == 0) return Air.Inst.Ref.bool_true; | 30448 | if (error_set_type.names.len == 0) return .bool_true; |
| 30378 | }, | 30449 | }, |
| 30379 | .inferred_error_set_type => |ies_index| blk: { | 30450 | .inferred_error_set_type => |func_index| blk: { |
| 30380 | // If the error set is empty, we must return a comptime true or false. | 30451 | // If the error set is empty, we must return a comptime true or false. |
| 30381 | // However we want to avoid unnecessarily resolving an inferred error set | 30452 | // However we want to avoid unnecessarily resolving an inferred error set |
| 30382 | // in case it is already non-empty. | 30453 | // in case it is already non-empty. |
| 30383 | const ies = mod.inferredErrorSetPtr(ies_index); | 30454 | switch (ip.funcIesResolved(func_index).*) { |
| 30384 | if (ies.is_anyerror) break :blk; | 30455 | .anyerror_type => break :blk, |
| 30385 | if (ies.errors.count() != 0) break :blk; | 30456 | .none => {}, |
| 30457 | else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk, | ||
| 30458 | } | ||
| 30386 | if (maybe_operand_val == null) { | 30459 | if (maybe_operand_val == null) { |
| 30387 | // Try to avoid resolving inferred error set if possible. | 30460 | if (sema.fn_ret_ty_ies) |ies| if (ies.func == func_index) { |
| 30388 | if (ies.errors.count() != 0) break :blk; | 30461 | // Try to avoid resolving inferred error set if possible. |
| 30389 | if (ies.is_anyerror) break :blk; | 30462 | for (ies.inferred_error_sets.keys()) |other_ies_index| { |
| 30390 | for (ies.inferred_error_sets.keys()) |other_ies_index| { | 30463 | if (set_ty == other_ies_index) continue; |
| 30391 | if (ies_index == other_ies_index) continue; | 30464 | const other_resolved = |
| 30392 | try sema.resolveInferredErrorSet(block, src, other_ies_index); | 30465 | try sema.resolveInferredErrorSet(block, src, other_ies_index); |
| 30393 | const other_ies = mod.inferredErrorSetPtr(other_ies_index); | 30466 | if (other_resolved == .anyerror_type) { |
| 30394 | if (other_ies.is_anyerror) { | 30467 | ip.funcIesResolved(func_index).* = .anyerror_type; |
| 30395 | ies.is_anyerror = true; | 30468 | break :blk; |
| 30396 | ies.is_resolved = true; | 30469 | } |
| 30397 | break :blk; | 30470 | if (ip.indexToKey(other_resolved).error_set_type.names.len != 0) |
| 30471 | break :blk; | ||
| 30398 | } | 30472 | } |
| 30399 | 30473 | return .bool_true; | |
| 30400 | if (other_ies.errors.count() != 0) break :blk; | 30474 | }; |
| 30401 | } | 30475 | const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty); |
| 30402 | if (ies.func == sema.owner_func_index) { | 30476 | if (resolved_ty == .anyerror_type) |
| 30403 | // We're checking the inferred errorset of the current function and none of | 30477 | break :blk; |
| 30404 | // its child inferred error sets contained any errors meaning that any value | 30478 | if (ip.indexToKey(resolved_ty).error_set_type.names.len == 0) |
| 30405 | // so far with this type can't contain errors either. | 30479 | return .bool_true; |
| 30406 | return Air.Inst.Ref.bool_true; | ||
| 30407 | } | ||
| 30408 | try sema.resolveInferredErrorSet(block, src, ies_index); | ||
| 30409 | if (ies.is_anyerror) break :blk; | ||
| 30410 | if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true; | ||
| 30411 | } | 30480 | } |
| 30412 | }, | 30481 | }, |
| 30413 | else => unreachable, | 30482 | else => unreachable, |
| ... | @@ -30419,12 +30488,12 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -30419,12 +30488,12 @@ fn analyzeIsNonErrComptimeOnly( |
| 30419 | return sema.addConstUndef(Type.bool); | 30488 | return sema.addConstUndef(Type.bool); |
| 30420 | } | 30489 | } |
| 30421 | if (err_union.getErrorName(mod) == .none) { | 30490 | if (err_union.getErrorName(mod) == .none) { |
| 30422 | return Air.Inst.Ref.bool_true; | 30491 | return .bool_true; |
| 30423 | } else { | 30492 | } else { |
| 30424 | return Air.Inst.Ref.bool_false; | 30493 | return .bool_false; |
| 30425 | } | 30494 | } |
| 30426 | } | 30495 | } |
| 30427 | return Air.Inst.Ref.none; | 30496 | return .none; |
| 30428 | } | 30497 | } |
| 30429 | 30498 | ||
| 30430 | fn analyzeIsNonErr( | 30499 | fn analyzeIsNonErr( |
| ... | @@ -31365,16 +31434,19 @@ fn wrapErrorUnionSet( | ... | @@ -31365,16 +31434,19 @@ fn wrapErrorUnionSet( |
| 31365 | if (error_set_type.nameIndex(ip, expected_name) != null) break :ok; | 31434 | if (error_set_type.nameIndex(ip, expected_name) != null) break :ok; |
| 31366 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); | 31435 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); |
| 31367 | }, | 31436 | }, |
| 31368 | .inferred_error_set_type => |ies_index| ok: { | 31437 | .inferred_error_set_type => |func_index| ok: { |
| 31369 | const ies = mod.inferredErrorSetPtr(ies_index); | ||
| 31370 | const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; | ||
| 31371 | |||
| 31372 | // We carefully do this in an order that avoids unnecessarily | 31438 | // We carefully do this in an order that avoids unnecessarily |
| 31373 | // resolving the destination error set type. | 31439 | // resolving the destination error set type. |
| 31374 | if (ies.is_anyerror) break :ok; | 31440 | const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name; |
| 31375 | 31441 | switch (ip.funcIesResolved(func_index).*) { | |
| 31376 | if (ies.errors.contains(expected_name)) break :ok; | 31442 | .anyerror_type => break :ok, |
| 31377 | if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok; | 31443 | .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) { |
| 31444 | break :ok; | ||
| 31445 | }, | ||
| 31446 | else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) { | ||
| 31447 | break :ok; | ||
| 31448 | }, | ||
| 31449 | } | ||
| 31378 | 31450 | ||
| 31379 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); | 31451 | return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty); |
| 31380 | }, | 31452 | }, |
| ... | @@ -32862,10 +32934,13 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { | ... | @@ -32862,10 +32934,13 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { |
| 32862 | }; | 32934 | }; |
| 32863 | } | 32935 | } |
| 32864 | 32936 | ||
| 32865 | pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void { | 32937 | pub fn resolveFnTypes(sema: *Sema, block: *Block, src: LazySrcLoc, fn_ty: Type) CompileError!void { |
| 32866 | const mod = sema.mod; | 32938 | const mod = sema.mod; |
| 32867 | const ip = &mod.intern_pool; | 32939 | const ip = &mod.intern_pool; |
| 32868 | const fn_ty_info = mod.typeToFunc(fn_ty).?; | 32940 | const fn_ty_info = mod.typeToFunc(fn_ty).?; |
| 32941 | |||
| 32942 | if (sema.fn_ret_ty_ies) |ies| try sema.resolveInferredErrorSetPtr(block, src, ies); | ||
| 32943 | |||
| 32869 | try sema.resolveTypeFully(fn_ty_info.return_type.toType()); | 32944 | try sema.resolveTypeFully(fn_ty_info.return_type.toType()); |
| 32870 | 32945 | ||
| 32871 | if (mod.comp.bin_file.options.error_return_tracing and fn_ty_info.return_type.toType().isError(mod)) { | 32946 | if (mod.comp.bin_file.options.error_return_tracing and fn_ty_info.return_type.toType().isError(mod)) { |
| ... | @@ -33173,6 +33248,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi | ... | @@ -33173,6 +33248,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 33173 | .owner_decl_index = decl_index, | 33248 | .owner_decl_index = decl_index, |
| 33174 | .func_index = .none, | 33249 | .func_index = .none, |
| 33175 | .fn_ret_ty = Type.void, | 33250 | .fn_ret_ty = Type.void, |
| 33251 | .fn_ret_ty_ies = null, | ||
| 33176 | .owner_func_index = .none, | 33252 | .owner_func_index = .none, |
| 33177 | .comptime_mutable_decls = &comptime_mutable_decls, | 33253 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 33178 | }; | 33254 | }; |
| ... | @@ -33223,6 +33299,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi | ... | @@ -33223,6 +33299,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 33223 | .owner_decl_index = decl_index, | 33299 | .owner_decl_index = decl_index, |
| 33224 | .func_index = .none, | 33300 | .func_index = .none, |
| 33225 | .fn_ret_ty = Type.void, | 33301 | .fn_ret_ty = Type.void, |
| 33302 | .fn_ret_ty_ies = null, | ||
| 33226 | .owner_func_index = .none, | 33303 | .owner_func_index = .none, |
| 33227 | .comptime_mutable_decls = undefined, | 33304 | .comptime_mutable_decls = undefined, |
| 33228 | }; | 33305 | }; |
| ... | @@ -33797,30 +33874,31 @@ fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) Compi | ... | @@ -33797,30 +33874,31 @@ fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) Compi |
| 33797 | union_obj.status = .have_field_types; | 33874 | union_obj.status = .have_field_types; |
| 33798 | } | 33875 | } |
| 33799 | 33876 | ||
| 33877 | /// Returns a normal error set corresponding to the fully populated inferred | ||
| 33878 | /// error set. | ||
| 33800 | fn resolveInferredErrorSet( | 33879 | fn resolveInferredErrorSet( |
| 33801 | sema: *Sema, | 33880 | sema: *Sema, |
| 33802 | block: *Block, | 33881 | block: *Block, |
| 33803 | src: LazySrcLoc, | 33882 | src: LazySrcLoc, |
| 33804 | ies_index: Module.InferredErrorSet.Index, | 33883 | ies_index: InternPool.Index, |
| 33805 | ) CompileError!void { | 33884 | ) CompileError!InternPool.Index { |
| 33806 | const mod = sema.mod; | 33885 | const mod = sema.mod; |
| 33807 | const ip = &mod.intern_pool; | 33886 | const ip = &mod.intern_pool; |
| 33808 | const ies = mod.inferredErrorSetPtr(ies_index); | 33887 | const func_index = ip.iesFuncIndex(ies_index); |
| 33809 | 33888 | const func = mod.funcInfo(func_index); | |
| 33810 | if (ies.is_resolved) return; | 33889 | const resolved_ty = func.resolvedErrorSet(ip).*; |
| 33811 | 33890 | if (resolved_ty != .none) return resolved_ty; | |
| 33812 | const func = mod.funcInfo(ies.func); | 33891 | if (func.analysis(ip).state == .in_progress) |
| 33813 | if (func.analysis(ip).state == .in_progress) { | ||
| 33814 | return sema.fail(block, src, "unable to resolve inferred error set", .{}); | 33892 | return sema.fail(block, src, "unable to resolve inferred error set", .{}); |
| 33815 | } | ||
| 33816 | 33893 | ||
| 33817 | // In order to ensure that all dependencies are properly added to the set, we | 33894 | // In order to ensure that all dependencies are properly added to the set, |
| 33818 | // need to ensure the function body is analyzed of the inferred error set. | 33895 | // we need to ensure the function body is analyzed of the inferred error |
| 33819 | // However, in the case of comptime/inline function calls with inferred error sets, | 33896 | // set. However, in the case of comptime/inline function calls with |
| 33820 | // each call gets a new InferredErrorSet object, which contains the same | 33897 | // inferred error sets, each call gets a new InferredErrorSet object, which |
| 33821 | // `InternPool.Index`. Not only is the function not relevant to the inferred error set | 33898 | // contains the `InternPool.Index` of the callee. Not only is the function |
| 33822 | // in this case, it may be a generic function which would cause an assertion failure | 33899 | // not relevant to the inferred error set in this case, it may be a generic |
| 33823 | // if we called `ensureFuncBodyAnalyzed` on it here. | 33900 | // function which would cause an assertion failure if we called |
| 33901 | // `ensureFuncBodyAnalyzed` on it here. | ||
| 33824 | const ies_func_owner_decl = mod.declPtr(func.owner_decl); | 33902 | const ies_func_owner_decl = mod.declPtr(func.owner_decl); |
| 33825 | const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?; | 33903 | const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?; |
| 33826 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, | 33904 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, |
| ... | @@ -33828,7 +33906,7 @@ fn resolveInferredErrorSet( | ... | @@ -33828,7 +33906,7 @@ fn resolveInferredErrorSet( |
| 33828 | // so here we can simply skip this case. | 33906 | // so here we can simply skip this case. |
| 33829 | if (ies_func_info.return_type == .generic_poison_type) { | 33907 | if (ies_func_info.return_type == .generic_poison_type) { |
| 33830 | assert(ies_func_info.cc == .Inline); | 33908 | assert(ies_func_info.cc == .Inline); |
| 33831 | } else if (mod.typeToInferredErrorSet(ies_func_info.return_type.toType().errorUnionSet(mod)).? == ies) { | 33909 | } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { |
| 33832 | if (ies_func_info.is_generic) { | 33910 | if (ies_func_info.is_generic) { |
| 33833 | const msg = msg: { | 33911 | const msg = msg: { |
| 33834 | const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{}); | 33912 | const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{}); |
| ... | @@ -33841,33 +33919,62 @@ fn resolveInferredErrorSet( | ... | @@ -33841,33 +33919,62 @@ fn resolveInferredErrorSet( |
| 33841 | } | 33919 | } |
| 33842 | // In this case we are dealing with the actual InferredErrorSet object that | 33920 | // In this case we are dealing with the actual InferredErrorSet object that |
| 33843 | // corresponds to the function, not one created to track an inline/comptime call. | 33921 | // corresponds to the function, not one created to track an inline/comptime call. |
| 33844 | try sema.ensureFuncBodyAnalyzed(ies.func); | 33922 | try sema.ensureFuncBodyAnalyzed(func_index); |
| 33845 | } | 33923 | } |
| 33846 | 33924 | ||
| 33847 | ies.is_resolved = true; | 33925 | // This will now have been resolved by the logic at the end of `Module.analyzeFnBody` |
| 33926 | // which calls `resolveInferredErrorSetPtr`. | ||
| 33927 | const final_resolved_ty = func.resolvedErrorSet(ip).*; | ||
| 33928 | assert(final_resolved_ty != .none); | ||
| 33929 | return final_resolved_ty; | ||
| 33930 | } | ||
| 33931 | |||
| 33932 | fn resolveInferredErrorSetPtr( | ||
| 33933 | sema: *Sema, | ||
| 33934 | block: *Block, | ||
| 33935 | src: LazySrcLoc, | ||
| 33936 | ies: *InferredErrorSet, | ||
| 33937 | ) CompileError!void { | ||
| 33938 | const mod = sema.mod; | ||
| 33939 | const ip = &mod.intern_pool; | ||
| 33940 | |||
| 33941 | const func = mod.funcInfo(ies.func); | ||
| 33942 | if (func.resolvedErrorSet(ip).* != .none) return; | ||
| 33943 | |||
| 33944 | const ies_index = ip.errorUnionSet(sema.fn_ret_ty.toIntern()); | ||
| 33848 | 33945 | ||
| 33849 | for (ies.inferred_error_sets.keys()) |other_ies_index| { | 33946 | for (ies.inferred_error_sets.keys()) |other_ies_index| { |
| 33850 | if (ies_index == other_ies_index) continue; | 33947 | if (ies_index == other_ies_index) continue; |
| 33851 | try sema.resolveInferredErrorSet(block, src, other_ies_index); | 33948 | switch (try sema.resolveInferredErrorSet(block, src, other_ies_index)) { |
| 33852 | 33949 | .anyerror_type => { | |
| 33853 | const other_ies = mod.inferredErrorSetPtr(other_ies_index); | 33950 | func.resolvedErrorSet(ip).* = .anyerror_type; |
| 33854 | for (other_ies.errors.keys()) |key| { | 33951 | return; |
| 33855 | try ies.errors.put(sema.gpa, key, {}); | 33952 | }, |
| 33953 | else => |error_set_ty_index| { | ||
| 33954 | const names = ip.indexToKey(error_set_ty_index).error_set_type.names; | ||
| 33955 | for (names.get(ip)) |name| { | ||
| 33956 | try ies.errors.put(sema.arena, name, {}); | ||
| 33957 | } | ||
| 33958 | }, | ||
| 33856 | } | 33959 | } |
| 33857 | if (other_ies.is_anyerror) | ||
| 33858 | ies.is_anyerror = true; | ||
| 33859 | } | 33960 | } |
| 33961 | |||
| 33962 | const resolved_error_set_ty = try mod.errorSetFromUnsortedNames(ies.errors.keys()); | ||
| 33963 | func.resolvedErrorSet(ip).* = resolved_error_set_ty.toIntern(); | ||
| 33860 | } | 33964 | } |
| 33861 | 33965 | ||
| 33862 | fn resolveInferredErrorSetTy( | 33966 | fn resolveInferredErrorSetTy( |
| 33863 | sema: *Sema, | 33967 | sema: *Sema, |
| 33864 | block: *Block, | 33968 | block: *Block, |
| 33865 | src: LazySrcLoc, | 33969 | src: LazySrcLoc, |
| 33866 | ty: Type, | 33970 | ty: InternPool.Index, |
| 33867 | ) CompileError!void { | 33971 | ) CompileError!InternPool.Index { |
| 33868 | const mod = sema.mod; | 33972 | const mod = sema.mod; |
| 33869 | if (mod.typeToInferredErrorSetIndex(ty).unwrap()) |ies_index| { | 33973 | const ip = &mod.intern_pool; |
| 33870 | try sema.resolveInferredErrorSet(block, src, ies_index); | 33974 | switch (ip.indexToKey(ty)) { |
| 33975 | .error_set_type => return ty, | ||
| 33976 | .inferred_error_set_type => return sema.resolveInferredErrorSet(block, src, ty), | ||
| 33977 | else => unreachable, | ||
| 33871 | } | 33978 | } |
| 33872 | } | 33979 | } |
| 33873 | 33980 | ||
| ... | @@ -33937,6 +34044,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -33937,6 +34044,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 33937 | .owner_decl_index = decl_index, | 34044 | .owner_decl_index = decl_index, |
| 33938 | .func_index = .none, | 34045 | .func_index = .none, |
| 33939 | .fn_ret_ty = Type.void, | 34046 | .fn_ret_ty = Type.void, |
| 34047 | .fn_ret_ty_ies = null, | ||
| 33940 | .owner_func_index = .none, | 34048 | .owner_func_index = .none, |
| 33941 | .comptime_mutable_decls = &comptime_mutable_decls, | 34049 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 33942 | }; | 34050 | }; |
| ... | @@ -34282,6 +34390,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -34282,6 +34390,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 34282 | .owner_decl_index = decl_index, | 34390 | .owner_decl_index = decl_index, |
| 34283 | .func_index = .none, | 34391 | .func_index = .none, |
| 34284 | .fn_ret_ty = Type.void, | 34392 | .fn_ret_ty = Type.void, |
| 34393 | .fn_ret_ty_ies = null, | ||
| 34285 | .owner_func_index = .none, | 34394 | .owner_func_index = .none, |
| 34286 | .comptime_mutable_decls = &comptime_mutable_decls, | 34395 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 34287 | }; | 34396 | }; |
| ... | @@ -34893,6 +35002,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -34893,6 +35002,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 34893 | .var_args_param_type, | 35002 | .var_args_param_type, |
| 34894 | .none, | 35003 | .none, |
| 34895 | => unreachable, | 35004 | => unreachable, |
| 35005 | |||
| 34896 | _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) { | 35006 | _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) { |
| 34897 | .type_int_signed, // i0 handled above | 35007 | .type_int_signed, // i0 handled above |
| 34898 | .type_int_unsigned, // u0 handled above | 35008 | .type_int_unsigned, // u0 handled above |
| ... | @@ -34901,6 +35011,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -34901,6 +35011,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 34901 | .type_optional, // ?noreturn handled above | 35011 | .type_optional, // ?noreturn handled above |
| 34902 | .type_anyframe, | 35012 | .type_anyframe, |
| 34903 | .type_error_union, | 35013 | .type_error_union, |
| 35014 | .type_anyerror_union, | ||
| 34904 | .type_error_set, | 35015 | .type_error_set, |
| 34905 | .type_inferred_error_set, | 35016 | .type_inferred_error_set, |
| 34906 | .type_opaque, | 35017 | .type_opaque, |
| ... | @@ -36354,7 +36465,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { | ... | @@ -36354,7 +36465,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { |
| 36354 | const arena = sema.arena; | 36465 | const arena = sema.arena; |
| 36355 | const lhs_names = lhs.errorSetNames(mod); | 36466 | const lhs_names = lhs.errorSetNames(mod); |
| 36356 | const rhs_names = rhs.errorSetNames(mod); | 36467 | const rhs_names = rhs.errorSetNames(mod); |
| 36357 | var names: Module.InferredErrorSet.NameMap = .{}; | 36468 | var names: InferredErrorSet.NameMap = .{}; |
| 36358 | try names.ensureUnusedCapacity(arena, lhs_names.len); | 36469 | try names.ensureUnusedCapacity(arena, lhs_names.len); |
| 36359 | 36470 | ||
| 36360 | for (lhs_names) |name| { | 36471 | for (lhs_names) |name| { |
src/codegen/llvm.zig+12-13| ... | @@ -6061,8 +6061,6 @@ pub const FuncGen = struct { | ... | @@ -6061,8 +6061,6 @@ pub const FuncGen = struct { |
| 6061 | .is_var_args = false, | 6061 | .is_var_args = false, |
| 6062 | .is_generic = false, | 6062 | .is_generic = false, |
| 6063 | .is_noinline = false, | 6063 | .is_noinline = false, |
| 6064 | .align_is_generic = false, | ||
| 6065 | .cc_is_generic = false, | ||
| 6066 | .section_is_generic = false, | 6064 | .section_is_generic = false, |
| 6067 | .addrspace_is_generic = false, | 6065 | .addrspace_is_generic = false, |
| 6068 | }); | 6066 | }); |
| ... | @@ -10657,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField { | ... | @@ -10657,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField { |
| 10657 | } | 10655 | } |
| 10658 | 10656 | ||
| 10659 | fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool { | 10657 | fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool { |
| 10660 | if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false; | 10658 | const return_type = fn_info.return_type.toType(); |
| 10659 | if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) return false; | ||
| 10661 | 10660 | ||
| 10662 | const target = mod.getTarget(); | 10661 | const target = mod.getTarget(); |
| 10663 | switch (fn_info.cc) { | 10662 | switch (fn_info.cc) { |
| 10664 | .Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod), | 10663 | .Unspecified, .Inline => return isByRef(return_type, mod), |
| 10665 | .C => switch (target.cpu.arch) { | 10664 | .C => switch (target.cpu.arch) { |
| 10666 | .mips, .mipsel => return false, | 10665 | .mips, .mipsel => return false, |
| 10667 | .x86_64 => switch (target.os.tag) { | 10666 | .x86_64 => switch (target.os.tag) { |
| 10668 | .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory, | 10667 | .windows => return x86_64_abi.classifyWindows(return_type, mod) == .memory, |
| 10669 | else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod), | 10668 | else => return firstParamSRetSystemV(return_type, mod), |
| 10670 | }, | 10669 | }, |
| 10671 | .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect, | 10670 | .wasm32 => return wasm_c_abi.classifyType(return_type, mod)[0] == .indirect, |
| 10672 | .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory, | 10671 | .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(return_type, mod) == .memory, |
| 10673 | .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) { | 10672 | .arm, .armeb => switch (arm_c_abi.classifyType(return_type, mod, .ret)) { |
| 10674 | .memory, .i64_array => return true, | 10673 | .memory, .i64_array => return true, |
| 10675 | .i32_array => |size| return size != 1, | 10674 | .i32_array => |size| return size != 1, |
| 10676 | .byval => return false, | 10675 | .byval => return false, |
| 10677 | }, | 10676 | }, |
| 10678 | .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory, | 10677 | .riscv32, .riscv64 => return riscv_c_abi.classifyType(return_type, mod) == .memory, |
| 10679 | else => return false, // TODO investigate C ABI for other architectures | 10678 | else => return false, // TODO investigate C ABI for other architectures |
| 10680 | }, | 10679 | }, |
| 10681 | .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod), | 10680 | .SysV => return firstParamSRetSystemV(return_type, mod), |
| 10682 | .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory, | 10681 | .Win64 => return x86_64_abi.classifyWindows(return_type, mod) == .memory, |
| 10683 | .Stdcall => return !isScalar(mod, fn_info.return_type.toType()), | 10682 | .Stdcall => return !isScalar(mod, return_type), |
| 10684 | else => return false, | 10683 | else => return false, |
| 10685 | } | 10684 | } |
| 10686 | } | 10685 | } |
src/link/Dwarf.zig+23-34| ... | @@ -1043,6 +1043,7 @@ pub fn commitDeclState( | ... | @@ -1043,6 +1043,7 @@ pub fn commitDeclState( |
| 1043 | var dbg_line_buffer = &decl_state.dbg_line; | 1043 | var dbg_line_buffer = &decl_state.dbg_line; |
| 1044 | var dbg_info_buffer = &decl_state.dbg_info; | 1044 | var dbg_info_buffer = &decl_state.dbg_info; |
| 1045 | const decl = mod.declPtr(decl_index); | 1045 | const decl = mod.declPtr(decl_index); |
| 1046 | const ip = &mod.intern_pool; | ||
| 1046 | 1047 | ||
| 1047 | const target_endian = self.target.cpu.arch.endian(); | 1048 | const target_endian = self.target.cpu.arch.endian(); |
| 1048 | 1049 | ||
| ... | @@ -1241,20 +1242,9 @@ pub fn commitDeclState( | ... | @@ -1241,20 +1242,9 @@ pub fn commitDeclState( |
| 1241 | while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) { | 1242 | while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) { |
| 1242 | const symbol = &decl_state.abbrev_table.items[sym_index]; | 1243 | const symbol = &decl_state.abbrev_table.items[sym_index]; |
| 1243 | const ty = symbol.type; | 1244 | const ty = symbol.type; |
| 1244 | const deferred: bool = blk: { | 1245 | if (ip.isErrorSetType(ty.toIntern())) continue; |
| 1245 | if (ty.isAnyError(mod)) break :blk true; | ||
| 1246 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 1247 | .inferred_error_set_type => |ies_index| { | ||
| 1248 | const ies = mod.inferredErrorSetPtr(ies_index); | ||
| 1249 | if (!ies.is_resolved) break :blk true; | ||
| 1250 | }, | ||
| 1251 | else => {}, | ||
| 1252 | } | ||
| 1253 | break :blk false; | ||
| 1254 | }; | ||
| 1255 | if (deferred) continue; | ||
| 1256 | 1246 | ||
| 1257 | symbol.offset = @as(u32, @intCast(dbg_info_buffer.items.len)); | 1247 | symbol.offset = @intCast(dbg_info_buffer.items.len); |
| 1258 | try decl_state.addDbgInfoType(mod, di_atom_index, ty); | 1248 | try decl_state.addDbgInfoType(mod, di_atom_index, ty); |
| 1259 | } | 1249 | } |
| 1260 | } | 1250 | } |
| ... | @@ -1265,18 +1255,7 @@ pub fn commitDeclState( | ... | @@ -1265,18 +1255,7 @@ pub fn commitDeclState( |
| 1265 | if (reloc.target) |target| { | 1255 | if (reloc.target) |target| { |
| 1266 | const symbol = decl_state.abbrev_table.items[target]; | 1256 | const symbol = decl_state.abbrev_table.items[target]; |
| 1267 | const ty = symbol.type; | 1257 | const ty = symbol.type; |
| 1268 | const deferred: bool = blk: { | 1258 | if (ip.isErrorSetType(ty.toIntern())) { |
| 1269 | if (ty.isAnyError(mod)) break :blk true; | ||
| 1270 | switch (mod.intern_pool.indexToKey(ty.ip_index)) { | ||
| 1271 | .inferred_error_set_type => |ies_index| { | ||
| 1272 | const ies = mod.inferredErrorSetPtr(ies_index); | ||
| 1273 | if (!ies.is_resolved) break :blk true; | ||
| 1274 | }, | ||
| 1275 | else => {}, | ||
| 1276 | } | ||
| 1277 | break :blk false; | ||
| 1278 | }; | ||
| 1279 | if (deferred) { | ||
| 1280 | log.debug("resolving %{d} deferred until flush", .{target}); | 1259 | log.debug("resolving %{d} deferred until flush", .{target}); |
| 1281 | try self.global_abbrev_relocs.append(gpa, .{ | 1260 | try self.global_abbrev_relocs.append(gpa, .{ |
| 1282 | .target = null, | 1261 | .target = null, |
| ... | @@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void { | ... | @@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void { |
| 2505 | defer arena_alloc.deinit(); | 2484 | defer arena_alloc.deinit(); |
| 2506 | const arena = arena_alloc.allocator(); | 2485 | const arena = arena_alloc.allocator(); |
| 2507 | 2486 | ||
| 2508 | // TODO: don't create a zig type for this, just make the dwarf info | ||
| 2509 | // without touching the zig type system. | ||
| 2510 | const names = try arena.dupe(InternPool.NullTerminatedString, module.global_error_set.keys()); | ||
| 2511 | std.mem.sort(InternPool.NullTerminatedString, names, {}, InternPool.NullTerminatedString.indexLessThan); | ||
| 2512 | |||
| 2513 | const error_ty = try module.intern(.{ .error_set_type = .{ .names = names } }); | ||
| 2514 | var dbg_info_buffer = std.ArrayList(u8).init(arena); | 2487 | var dbg_info_buffer = std.ArrayList(u8).init(arena); |
| 2515 | try addDbgInfoErrorSet(module, error_ty.toType(), self.target, &dbg_info_buffer); | 2488 | try addDbgInfoErrorSetNames( |
| 2489 | module, | ||
| 2490 | Type.anyerror, | ||
| 2491 | module.global_error_set.keys(), | ||
| 2492 | self.target, | ||
| 2493 | &dbg_info_buffer, | ||
| 2494 | ); | ||
| 2516 | 2495 | ||
| 2517 | const di_atom_index = try self.createAtom(.di_atom); | 2496 | const di_atom_index = try self.createAtom(.di_atom); |
| 2518 | log.debug("updateDeclDebugInfoAllocation in flushModule", .{}); | 2497 | log.debug("updateDeclDebugInfoAllocation in flushModule", .{}); |
| 2519 | try self.updateDeclDebugInfoAllocation(di_atom_index, @as(u32, @intCast(dbg_info_buffer.items.len))); | 2498 | try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len)); |
| 2520 | log.debug("writeDeclDebugInfo in flushModule", .{}); | 2499 | log.debug("writeDeclDebugInfo in flushModule", .{}); |
| 2521 | try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items); | 2500 | try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items); |
| 2522 | 2501 | ||
| ... | @@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet( | ... | @@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet( |
| 2633 | ty: Type, | 2612 | ty: Type, |
| 2634 | target: std.Target, | 2613 | target: std.Target, |
| 2635 | dbg_info_buffer: *std.ArrayList(u8), | 2614 | dbg_info_buffer: *std.ArrayList(u8), |
| 2615 | ) !void { | ||
| 2616 | return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod), target, dbg_info_buffer); | ||
| 2617 | } | ||
| 2618 | |||
| 2619 | fn addDbgInfoErrorSetNames( | ||
| 2620 | mod: *Module, | ||
| 2621 | /// Used for printing the type name only. | ||
| 2622 | ty: Type, | ||
| 2623 | error_names: []const InternPool.NullTerminatedString, | ||
| 2624 | target: std.Target, | ||
| 2625 | dbg_info_buffer: *std.ArrayList(u8), | ||
| 2636 | ) !void { | 2626 | ) !void { |
| 2637 | const target_endian = target.cpu.arch.endian(); | 2627 | const target_endian = target.cpu.arch.endian(); |
| 2638 | 2628 | ||
| ... | @@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet( | ... | @@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet( |
| 2655 | // DW.AT.const_value, DW.FORM.data8 | 2645 | // DW.AT.const_value, DW.FORM.data8 |
| 2656 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian); | 2646 | mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian); |
| 2657 | 2647 | ||
| 2658 | const error_names = ty.errorSetNames(mod); | ||
| 2659 | for (error_names) |error_name_ip| { | 2648 | for (error_names) |error_name_ip| { |
| 2660 | const int = try mod.getErrorValue(error_name_ip); | 2649 | const int = try mod.getErrorValue(error_name_ip); |
| 2661 | const error_name = mod.intern_pool.stringToSlice(error_name_ip); | 2650 | const error_name = mod.intern_pool.stringToSlice(error_name_ip); |
src/type.zig+33-34| ... | @@ -251,20 +251,19 @@ pub const Type = struct { | ... | @@ -251,20 +251,19 @@ pub const Type = struct { |
| 251 | return; | 251 | return; |
| 252 | }, | 252 | }, |
| 253 | .inferred_error_set_type => |index| { | 253 | .inferred_error_set_type => |index| { |
| 254 | const ies = mod.inferredErrorSetPtr(index); | 254 | const func = mod.iesFuncIndex(index); |
| 255 | const func = ies.func; | ||
| 256 | |||
| 257 | try writer.writeAll("@typeInfo(@typeInfo(@TypeOf("); | 255 | try writer.writeAll("@typeInfo(@typeInfo(@TypeOf("); |
| 258 | const owner_decl = mod.funcOwnerDeclPtr(func); | 256 | const owner_decl = mod.funcOwnerDeclPtr(func); |
| 259 | try owner_decl.renderFullyQualifiedName(mod, writer); | 257 | try owner_decl.renderFullyQualifiedName(mod, writer); |
| 260 | try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set"); | 258 | try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set"); |
| 261 | }, | 259 | }, |
| 262 | .error_set_type => |error_set_type| { | 260 | .error_set_type => |error_set_type| { |
| 261 | const ip = &mod.intern_pool; | ||
| 263 | const names = error_set_type.names; | 262 | const names = error_set_type.names; |
| 264 | try writer.writeAll("error{"); | 263 | try writer.writeAll("error{"); |
| 265 | for (names, 0..) |name, i| { | 264 | for (names.get(ip), 0..) |name, i| { |
| 266 | if (i != 0) try writer.writeByte(','); | 265 | if (i != 0) try writer.writeByte(','); |
| 267 | try writer.print("{}", .{name.fmt(&mod.intern_pool)}); | 266 | try writer.print("{}", .{name.fmt(ip)}); |
| 268 | } | 267 | } |
| 269 | try writer.writeAll("}"); | 268 | try writer.writeAll("}"); |
| 270 | }, | 269 | }, |
| ... | @@ -2051,21 +2050,19 @@ pub const Type = struct { | ... | @@ -2051,21 +2050,19 @@ pub const Type = struct { |
| 2051 | 2050 | ||
| 2052 | /// Asserts that the type is an error union. | 2051 | /// Asserts that the type is an error union. |
| 2053 | pub fn errorUnionSet(ty: Type, mod: *Module) Type { | 2052 | pub fn errorUnionSet(ty: Type, mod: *Module) Type { |
| 2054 | return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.error_set_type.toType(); | 2053 | return mod.intern_pool.errorUnionSet(ty.toIntern()).toType(); |
| 2055 | } | 2054 | } |
| 2056 | 2055 | ||
| 2057 | /// Returns false for unresolved inferred error sets. | 2056 | /// Returns false for unresolved inferred error sets. |
| 2058 | pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool { | 2057 | pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool { |
| 2058 | const ip = &mod.intern_pool; | ||
| 2059 | return switch (ty.toIntern()) { | 2059 | return switch (ty.toIntern()) { |
| 2060 | .anyerror_type => false, | 2060 | .anyerror_type => false, |
| 2061 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2061 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 2062 | .error_set_type => |error_set_type| error_set_type.names.len == 0, | 2062 | .error_set_type => |error_set_type| error_set_type.names.len == 0, |
| 2063 | .inferred_error_set_type => |index| { | 2063 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2064 | const inferred_error_set = mod.inferredErrorSetPtr(index); | 2064 | .none, .anyerror_type => false, |
| 2065 | // Can't know for sure. | 2065 | else => |t| ip.indexToKey(t).error_set_type.names.len == 0, |
| 2066 | if (!inferred_error_set.is_resolved) return false; | ||
| 2067 | if (inferred_error_set.is_anyerror) return false; | ||
| 2068 | return inferred_error_set.errors.count() == 0; | ||
| 2069 | }, | 2066 | }, |
| 2070 | else => unreachable, | 2067 | else => unreachable, |
| 2071 | }, | 2068 | }, |
| ... | @@ -2076,10 +2073,11 @@ pub const Type = struct { | ... | @@ -2076,10 +2073,11 @@ pub const Type = struct { |
| 2076 | /// Note that the result may be a false negative if the type did not get error set | 2073 | /// Note that the result may be a false negative if the type did not get error set |
| 2077 | /// resolution prior to this call. | 2074 | /// resolution prior to this call. |
| 2078 | pub fn isAnyError(ty: Type, mod: *Module) bool { | 2075 | pub fn isAnyError(ty: Type, mod: *Module) bool { |
| 2076 | const ip = &mod.intern_pool; | ||
| 2079 | return switch (ty.toIntern()) { | 2077 | return switch (ty.toIntern()) { |
| 2080 | .anyerror_type => true, | 2078 | .anyerror_type => true, |
| 2081 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2079 | else => switch (mod.intern_pool.indexToKey(ty.toIntern())) { |
| 2082 | .inferred_error_set_type => |i| mod.inferredErrorSetPtr(i).is_anyerror, | 2080 | .inferred_error_set_type => |i| ip.funcIesResolved(i).* == .anyerror_type, |
| 2083 | else => false, | 2081 | else => false, |
| 2084 | }, | 2082 | }, |
| 2085 | }; | 2083 | }; |
| ... | @@ -2103,13 +2101,11 @@ pub const Type = struct { | ... | @@ -2103,13 +2101,11 @@ pub const Type = struct { |
| 2103 | return switch (ty) { | 2101 | return switch (ty) { |
| 2104 | .anyerror_type => true, | 2102 | .anyerror_type => true, |
| 2105 | else => switch (ip.indexToKey(ty)) { | 2103 | else => switch (ip.indexToKey(ty)) { |
| 2106 | .error_set_type => |error_set_type| { | 2104 | .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null, |
| 2107 | return error_set_type.nameIndex(ip, name) != null; | 2105 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2108 | }, | 2106 | .anyerror_type => true, |
| 2109 | .inferred_error_set_type => |index| { | 2107 | .none => false, |
| 2110 | const ies = ip.inferredErrorSetPtrConst(index); | 2108 | else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null, |
| 2111 | if (ies.is_anyerror) return true; | ||
| 2112 | return ies.errors.contains(name); | ||
| 2113 | }, | 2109 | }, |
| 2114 | else => unreachable, | 2110 | else => unreachable, |
| 2115 | }, | 2111 | }, |
| ... | @@ -2129,12 +2125,14 @@ pub const Type = struct { | ... | @@ -2129,12 +2125,14 @@ pub const Type = struct { |
| 2129 | const field_name_interned = ip.getString(name).unwrap() orelse return false; | 2125 | const field_name_interned = ip.getString(name).unwrap() orelse return false; |
| 2130 | return error_set_type.nameIndex(ip, field_name_interned) != null; | 2126 | return error_set_type.nameIndex(ip, field_name_interned) != null; |
| 2131 | }, | 2127 | }, |
| 2132 | .inferred_error_set_type => |index| { | 2128 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2133 | const ies = ip.inferredErrorSetPtr(index); | 2129 | .anyerror_type => true, |
| 2134 | if (ies.is_anyerror) return true; | 2130 | .none => false, |
| 2135 | // If the string is not interned, then the field certainly is not present. | 2131 | else => |t| { |
| 2136 | const field_name_interned = ip.getString(name).unwrap() orelse return false; | 2132 | // If the string is not interned, then the field certainly is not present. |
| 2137 | return ies.errors.contains(field_name_interned); | 2133 | const field_name_interned = ip.getString(name).unwrap() orelse return false; |
| 2134 | return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null; | ||
| 2135 | }, | ||
| 2138 | }, | 2136 | }, |
| 2139 | else => unreachable, | 2137 | else => unreachable, |
| 2140 | }, | 2138 | }, |
| ... | @@ -2943,14 +2941,15 @@ pub const Type = struct { | ... | @@ -2943,14 +2941,15 @@ pub const Type = struct { |
| 2943 | } | 2941 | } |
| 2944 | 2942 | ||
| 2945 | // Asserts that `ty` is an error set and not `anyerror`. | 2943 | // Asserts that `ty` is an error set and not `anyerror`. |
| 2944 | // Asserts that `ty` is resolved if it is an inferred error set. | ||
| 2946 | pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString { | 2945 | pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString { |
| 2947 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 2946 | const ip = &mod.intern_pool; |
| 2948 | .error_set_type => |x| x.names, | 2947 | return switch (ip.indexToKey(ty.toIntern())) { |
| 2949 | .inferred_error_set_type => |index| { | 2948 | .error_set_type => |x| x.names.get(ip), |
| 2950 | const inferred_error_set = mod.inferredErrorSetPtr(index); | 2949 | .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { |
| 2951 | assert(inferred_error_set.is_resolved); | 2950 | .none => unreachable, // unresolved inferred error set |
| 2952 | assert(!inferred_error_set.is_anyerror); | 2951 | .anyerror_type => unreachable, |
| 2953 | return inferred_error_set.errors.keys(); | 2952 | else => |t| ip.indexToKey(t).error_set_type.names.get(ip), |
| 2954 | }, | 2953 | }, |
| 2955 | else => unreachable, | 2954 | else => unreachable, |
| 2956 | }; | 2955 | }; |