authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-08 23:39:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-18 19:02:05-07:00
logf3dc53f6b53e8493b341f82cb06a56e33e80e6b7
treea5c5c93af8ea6661214790e54e22fd5af3e0d6d6
parent55e89255e18163bcc153138a4883ec8d85e0d517

compiler: rework inferred error sets

* 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(
16691669
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 that1672 // 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 key1673 // 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 that1683 // 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.
54unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},54unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},
5555
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.
59allocated_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.
62inferred_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 names56/// 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 underlying57/// 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 _,
145137
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 }
149153
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 }
153157
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,
242247
243 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented248 /// 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) {
287292
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,
293298
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 the576 /// When a generic function is instantiated, branch_quota is inherited from the
569 /// active Sema context. Importantly, this value is also updated when an existing577 /// 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 }
605613
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 }
609618
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 };
614630
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 };
751767
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 }
755771
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 },
916932
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 },
922934
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 };
22532270
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 };
22642285
2265 /// Trailing:2286 /// Trailing:
2266 /// 0. For each parameter of generic_owner: Index2287 /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which
2267 /// - comptime parameter: the comptime-known value2288 /// is a regular error set corresponding to the finished inferred error set.
2268 /// - anytype parameter: the type of the runtime-known value2289 /// 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};
23132334
2314/// State that is mutable during semantic analysis. This data is not used for2335/// 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.
2316pub const FuncAnalysis = packed struct(u32) {2338pub 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,
23232349
2324 pub const State = enum(u8) {2350 pub const State = enum(u8) {
2325 /// This function has not yet undergone analysis, because we have not2351 /// 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);
27122738
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);
27182741
...@@ -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 },
27822805
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) },
27852808
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) },
28742893
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}
32293244
3230fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {3245fn 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
3256fn 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 or3285 .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}
32663288
3289fn indexToKeyFuncDecl(ip: *const InternPool, data: u32) Key.Func {
3290 _ = ip;
3291 _ = data;
3292 @panic("TODO");
3293}
3294
3295fn indexToKeyFuncInstance(ip: *const InternPool, data: u32) Key.Func {
3296 _ = ip;
3297 _ = data;
3298 @panic("TODO");
3299}
3300
3267fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {3301fn 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
3301pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {3335pub 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}
42124249
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);
42464283
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));
42704305
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 }
42764314
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}
42824321
4283pub const GetExternFuncKey = struct {4322pub 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}
43004339
4301pub const GetFuncDeclKey = struct {4340pub 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
4352pub 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
4394pub 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 generic4405 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};
43304415
4331pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index {4416pub 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 instantiations4466
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
4522pub 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}
43644562
4365pub const GetFuncInstanceKey = struct {4563pub 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};
43744573
4375pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, key: GetFuncInstanceKey) Allocator.Error!Index {4574pub 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}
43814667
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}
45834869
4584pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {4870pub 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}
45894875
4590pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {4876pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {
...@@ -4622,7 +4908,7 @@ fn addIndexesToMap(...@@ -4622,7 +4908,7 @@ fn addIndexesToMap(
4622fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {4908fn 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}
46274913
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),
47375026
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}
52075497
5208pub 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_type5498/// includes .comptime_int_type
5217pub fn isIntegerType(ip: *const InternPool, ty: Index) bool {5499pub 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}
52865568
5569pub 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.
5288pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {5574pub 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}
56005888
5601pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.InferredErrorSet.Index) *Module.InferredErrorSet {
5602 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
5603}
5604
5605pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.InferredErrorSet.Index) *const Module.InferredErrorSet {
5606 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
5607}
5608
5609pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl {5889pub 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}
56605940
5661pub 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
5675pub 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
5683pub fn createDecl(5941pub 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
62366495
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,
62406502
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}
63426604
6605pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool {
6606 return funcAnalysis(ip, i).inferred_error_set;
6607}
6608
6343pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index {6609pub 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
6626pub 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`.
6641pub 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`.
6653pub 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};
12991299
1300/// Some extern function struct memory is owned by the Decl's TypedValue.Managed
1301/// arena allocator.
1302pub 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.
1322pub 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
1392pub const DeclAdapter = struct {1300pub const DeclAdapter = struct {
1393 mod: *Module,1301 mod: *Module,
13941302
...@@ -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}
32223130
3223pub fn inferredErrorSetPtr(mod: *Module, index: InferredErrorSet.Index) *InferredErrorSet {
3224 return mod.intern_pool.inferredErrorSetPtr(index);
3225}
3226
3227pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace {3131pub 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();
52975204
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;
53005213
...@@ -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 than5359 // 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
65956508
6596pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type {6509pub 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}
66006514
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}
66156529
...@@ -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}
69586872
6959pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*InferredErrorSet {
6960 const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
6961 return mod.inferredErrorSetPtr(index);
6962}
6963
6964pub 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
6969pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl {6873pub 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}
69766880
6881pub fn iesFuncIndex(mod: *const Module, ies_index: InternPool.Index) InternPool.Index {
6882 return mod.intern_pool.iesFuncIndex(ies_index);
6883}
6884
6977pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func {6885pub 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
7044pub 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`.
40fn_ret_ty: Type,40fn_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`.
44fn_ret_ty_ies: ?*InferredErrorSet,
41branch_quota: u32 = default_branch_quota,45branch_quota: u32 = default_branch_quota,
42branch_count: u32 = 0,46branch_count: u32 = 0,
43/// Populated when returning `error.ComptimeBreak`. Used to communicate the47/// 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;
128pub const default_branch_quota = 1000;132pub const default_branch_quota = 1000;
129pub const default_reference_trace_len = 2;133pub const default_reference_trace_len = 2;
130134
135pub 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 resolve175/// 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 the177/// 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),
11211165
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()),
11241168
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 can1170 // 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);
33943438
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);
33973441
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 }
70197065
7020 // This `res2` is here instead of directly breaking from `res` due to a stage17066 // 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 }
70607106
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 }
70647110
7065 const result = result: {7111 const result = result: {
...@@ -7089,7 +7135,7 @@ fn analyzeCall(...@@ -7089,7 +7135,7 @@ fn analyzeCall(
70897135
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);
70937139
7094 // TODO: check whether any external comptime memory was mutated by the7140 // 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();
77707817
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 }
77887836
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 }
78027852
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();
78477897
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 }
78767927
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 }
78917944
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}
78957948
7896fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7949fn 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}
85718624
8625const Section = union(enum) {
8626 generic,
8627 default,
8628 explicit: InternPool.NullTerminatedString,
8629};
8630
8572fn funcCommon(8631fn 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 poison8638 /// 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 poison8641 /// null means generic poison
8583 cc: ?std.builtin.CallingConvention,8642 cc: ?std.builtin.CallingConvention,
8584 /// this might be Type.generic_poison8643 /// 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);
87108769
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(
87348823
8735 if (!has_body) break :i .none;8824 if (!has_body) break :i .none;
87368825
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, .{
87408829 .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;
87458830
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 }
87688850
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 });
87838864
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 };
87878877
...@@ -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 }
1025610344
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 }
1062410712
10625 try sema.resolveInferredErrorSetTy(block, src, operand_ty);10713 switch (try sema.resolveInferredErrorSetTy(block, src, operand_ty.toIntern())) {
1062610714 .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 };
1064010741
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 }
1066210751
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 }
1066810757
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 bodies10759 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;
1069610787
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 }
1070410795
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;
1071010800
10711 names.putAssumeCapacityNoClobber(error_name, {});10801 names.putAssumeCapacityNoClobber(error_name, {});
10712 }10802 }
10713 // No need to keep the hash map metadata correct; here we10803 // 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
1644416535
16445 try sema.queueFullTypeResolution(error_field_ty);16536 try sema.queueFullTypeResolution(error_field_ty);
1644616537
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 values16538 // Build our list of Error values
16451 // Optional value is only null if anyerror16539 // Optional value is only null if anyerror
16452 // Value can be zero-length slice otherwise16540 // 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 dupe16544 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 alignment16559 .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 };
1647916570
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 }
1648916580
16490 break :blk vals;16581 break :blk vals;
16582 },
16491 };16583 };
1649216584
16493 // Build our ?[]const Error value16585 // 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);
1805718149
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);
1950919603
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 }
2052620618
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);
2350723599
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 }
2775227844
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, to27847 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, and27853 }
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 }
2778427855
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 }
2779127863
...@@ -27800,17 +27872,15 @@ fn coerceInMemoryAllowedErrorSets(...@@ -27800,17 +27872,15 @@ fn coerceInMemoryAllowedErrorSets(
27800 },27872 },
2780127873
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 }
2781227882
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);
3034930420
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 }
3035430425
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 }
3036730438
30368 const maybe_operand_val = try sema.resolveMaybeUndefVal(operand);30439 const maybe_operand_val = try sema.resolveMaybeUndefVal(operand);
3036930440
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 set30452 // 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 }
3039930473 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 of30477 break :blk;
30404 // its child inferred error sets contained any errors meaning that any value30478 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}
3042930498
30430fn analyzeIsNonErr(30499fn 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 unnecessarily31438 // 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;
3137531441 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 }
3137831450
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}
3286432936
32865pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {32937pub 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());
3287032945
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}
3379933876
33877/// Returns a normal error set corresponding to the fully populated inferred
33878/// error set.
33800fn resolveInferredErrorSet(33879fn 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);
3380933888 const func = mod.funcInfo(func_index);
33810 if (ies.is_resolved) return;33889 const resolved_ty = func.resolvedErrorSet(ip).*;
3381133890 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 }
3381633893
33817 // In order to ensure that all dependencies are properly added to the set, we33894 // 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 same33897 // 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 set33898 // 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 failure33899 // 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 that33920 // 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 }
3384633924
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
33932fn 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());
3384833945
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)) {
3385233949 .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}
3386133965
33862fn resolveInferredErrorSetTy(33966fn 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}
3387333980
...@@ -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 above35007 .type_int_signed, // i0 handled above
34898 .type_int_unsigned, // u0 handled above35008 .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 above35011 .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);
3635936470
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}
1065810656
10659fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {10657fn 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;
1066110660
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 architectures10678 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;
10461047
1047 const target_endian = self.target.cpu.arch.endian();1048 const target_endian = self.target.cpu.arch.endian();
10481049
...@@ -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;
12561246
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();
25072486
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 );
25162495
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);
25222501
...@@ -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
2619fn 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();
26382628
...@@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet(...@@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet(
2655 // DW.AT.const_value, DW.FORM.data82645 // 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);
26572647
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 {
20512050
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 }
20562055
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 set2073 /// 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 }
29442942
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 };