authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-06 01:55:22+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-06 21:26:37+00:00
loga6ca20b9a1dfc7b6e8d004cb166c0714bb8db2db
tree8ecc7aae4a07f9e5a2fe1d2f2acfe0f40f5ea673
parent90ab8ea9e681a4ffac0b4dc500e3ec489014e12f
signaturelock-open Commit is signed but in an unrecognized format.

compiler: change representation of closures

This changes the representation of closures in Zir and Sema. Rather than a pair of instructions `closure_capture` and `closure_get`, the system now works as follows: * Each ZIR type declaration (`struct_decl` etc) contains a list of captures in the form of ZIR indices (or, for efficiency, direct references to parent captures). This is an ordered list; indexes into it are used to refer to captured values. * The `extended(closure_get)` ZIR instruction refers to a value in this list via a 16-bit index (limiting this index to 16 bits allows us to store this in `extended`). * `Module.Namespace` has a new field `captures` which contains the list of values captured in a given namespace. This is initialized based on the ZIR capture list whenever a type declaration is analyzed. This change eliminates `CaptureScope` from semantic analysis, which is a nice simplification; but the main motivation here is that this change is a prerequisite for #18816.

7 files changed, 563 insertions(+), 344 deletions(-)

lib/std/zig/AstGen.zig+149-96
...@@ -2205,7 +2205,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2205,7 +2205,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2205 },2205 },
2206 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2206 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2207 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2207 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2208 .namespace, .enum_namespace => break,2208 .namespace => break,
2209 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,2209 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2210 .top => unreachable,2210 .top => unreachable,
2211 }2211 }
...@@ -2279,7 +2279,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2279,7 +2279,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2279 try parent_gz.addDefer(defer_scope.index, defer_scope.len);2279 try parent_gz.addDefer(defer_scope.index, defer_scope.len);
2280 },2280 },
2281 .defer_error => scope = scope.cast(Scope.Defer).?.parent,2281 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2282 .namespace, .enum_namespace => break,2282 .namespace => break,
2283 .top => unreachable,2283 .top => unreachable,
2284 }2284 }
2285 }2285 }
...@@ -2412,7 +2412,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke...@@ -2412,7 +2412,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke
2412 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,2412 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
2413 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,2413 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
2414 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,2414 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
2415 .namespace, .enum_namespace => break,2415 .namespace => break,
2416 .top => unreachable,2416 .top => unreachable,
2417 }2417 }
2418 }2418 }
...@@ -2790,7 +2790,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2790,7 +2790,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2790 .@"resume",2790 .@"resume",
2791 .@"await",2791 .@"await",
2792 .ret_err_value_code,2792 .ret_err_value_code,
2793 .closure_get,
2794 .ret_ptr,2793 .ret_ptr,
2795 .ret_type,2794 .ret_type,
2796 .for_len,2795 .for_len,
...@@ -2860,7 +2859,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2860,7 +2859,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2860 .store_to_inferred_ptr,2859 .store_to_inferred_ptr,
2861 .resolve_inferred_alloc,2860 .resolve_inferred_alloc,
2862 .set_runtime_safety,2861 .set_runtime_safety,
2863 .closure_capture,
2864 .memcpy,2862 .memcpy,
2865 .memset,2863 .memset,
2866 .validate_deref,2864 .validate_deref,
...@@ -2928,7 +2926,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct {...@@ -2928,7 +2926,7 @@ fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct {
2928 const have_err_payload = defer_scope.remapped_err_code != .none;2926 const have_err_payload = defer_scope.remapped_err_code != .none;
2929 need_err_code = need_err_code or have_err_payload;2927 need_err_code = need_err_code or have_err_payload;
2930 },2928 },
2931 .namespace, .enum_namespace => unreachable,2929 .namespace => unreachable,
2932 .top => unreachable,2930 .top => unreachable,
2933 }2931 }
2934 }2932 }
...@@ -2998,7 +2996,7 @@ fn genDefers(...@@ -2998,7 +2996,7 @@ fn genDefers(
2998 .normal_only => continue,2996 .normal_only => continue,
2999 }2997 }
3000 },2998 },
3001 .namespace, .enum_namespace => unreachable,2999 .namespace => unreachable,
3002 .top => unreachable,3000 .top => unreachable,
3003 }3001 }
3004 }3002 }
...@@ -3042,7 +3040,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v...@@ -3042,7 +3040,7 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
3042 scope = s.parent;3040 scope = s.parent;
3043 },3041 },
3044 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,3042 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
3045 .namespace, .enum_namespace => unreachable,3043 .namespace => unreachable,
3046 .top => unreachable,3044 .top => unreachable,
3047 }3045 }
3048 }3046 }
...@@ -4732,7 +4730,7 @@ fn testDecl(...@@ -4732,7 +4730,7 @@ fn testDecl(
4732 },4730 },
4733 .gen_zir => s = s.cast(GenZir).?.parent,4731 .gen_zir => s = s.cast(GenZir).?.parent,
4734 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,4732 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
4735 .namespace, .enum_namespace => {4733 .namespace => {
4736 const ns = s.cast(Scope.Namespace).?;4734 const ns = s.cast(Scope.Namespace).?;
4737 if (ns.decls.get(name_str_index)) |i| {4735 if (ns.decls.get(name_str_index)) |i| {
4738 if (found_already) |f| {4736 if (found_already) |f| {
...@@ -4849,10 +4847,10 @@ fn structDeclInner(...@@ -4849,10 +4847,10 @@ fn structDeclInner(
4849 try gz.setStruct(decl_inst, .{4847 try gz.setStruct(decl_inst, .{
4850 .src_node = node,4848 .src_node = node,
4851 .layout = layout,4849 .layout = layout,
4850 .captures_len = 0,
4852 .fields_len = 0,4851 .fields_len = 0,
4853 .decls_len = 0,4852 .decls_len = 0,
4854 .backing_int_ref = .none,4853 .has_backing_int = false,
4855 .backing_int_body_len = 0,
4856 .known_non_opv = false,4854 .known_non_opv = false,
4857 .known_comptime_only = false,4855 .known_comptime_only = false,
4858 .is_tuple = false,4856 .is_tuple = false,
...@@ -5142,10 +5140,10 @@ fn structDeclInner(...@@ -5142,10 +5140,10 @@ fn structDeclInner(
5142 try gz.setStruct(decl_inst, .{5140 try gz.setStruct(decl_inst, .{
5143 .src_node = node,5141 .src_node = node,
5144 .layout = layout,5142 .layout = layout,
5143 .captures_len = @intCast(namespace.captures.count()),
5145 .fields_len = field_count,5144 .fields_len = field_count,
5146 .decls_len = decl_count,5145 .decls_len = decl_count,
5147 .backing_int_ref = backing_int_ref,5146 .has_backing_int = backing_int_ref != .none,
5148 .backing_int_body_len = @intCast(backing_int_body_len),
5149 .known_non_opv = known_non_opv,5147 .known_non_opv = known_non_opv,
5150 .known_comptime_only = known_comptime_only,5148 .known_comptime_only = known_comptime_only,
5151 .is_tuple = is_tuple,5149 .is_tuple = is_tuple,
...@@ -5159,15 +5157,22 @@ fn structDeclInner(...@@ -5159,15 +5157,22 @@ fn structDeclInner(
5159 const decls_slice = wip_members.declsSlice();5157 const decls_slice = wip_members.declsSlice();
5160 const fields_slice = wip_members.fieldsSlice();5158 const fields_slice = wip_members.fieldsSlice();
5161 const bodies_slice = astgen.scratch.items[bodies_start..];5159 const bodies_slice = astgen.scratch.items[bodies_start..];
5162 try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len +5160 try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + 2 +
5163 decls_slice.len + fields_slice.len + bodies_slice.len);5161 decls_slice.len + namespace.captures.count() + fields_slice.len + bodies_slice.len);
5164 astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]);5162 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5163 if (backing_int_ref != .none) {
5164 astgen.extra.appendAssumeCapacity(@intCast(backing_int_body_len));
5165 if (backing_int_body_len == 0) {
5166 astgen.extra.appendAssumeCapacity(@intFromEnum(backing_int_ref));
5167 } else {
5168 astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]);
5169 }
5170 }
5165 astgen.extra.appendSliceAssumeCapacity(decls_slice);5171 astgen.extra.appendSliceAssumeCapacity(decls_slice);
5166 astgen.extra.appendSliceAssumeCapacity(fields_slice);5172 astgen.extra.appendSliceAssumeCapacity(fields_slice);
5167 astgen.extra.appendSliceAssumeCapacity(bodies_slice);5173 astgen.extra.appendSliceAssumeCapacity(bodies_slice);
51685174
5169 block_scope.unstack();5175 block_scope.unstack();
5170 try gz.addNamespaceCaptures(&namespace);
5171 return decl_inst.toRef();5176 return decl_inst.toRef();
5172}5177}
51735178
...@@ -5368,6 +5373,7 @@ fn unionDeclInner(...@@ -5368,6 +5373,7 @@ fn unionDeclInner(
5368 .src_node = node,5373 .src_node = node,
5369 .layout = layout,5374 .layout = layout,
5370 .tag_type = arg_inst,5375 .tag_type = arg_inst,
5376 .captures_len = @intCast(namespace.captures.count()),
5371 .body_len = body_len,5377 .body_len = body_len,
5372 .fields_len = field_count,5378 .fields_len = field_count,
5373 .decls_len = decl_count,5379 .decls_len = decl_count,
...@@ -5379,13 +5385,13 @@ fn unionDeclInner(...@@ -5379,13 +5385,13 @@ fn unionDeclInner(
5379 wip_members.finishBits(bits_per_field);5385 wip_members.finishBits(bits_per_field);
5380 const decls_slice = wip_members.declsSlice();5386 const decls_slice = wip_members.declsSlice();
5381 const fields_slice = wip_members.fieldsSlice();5387 const fields_slice = wip_members.fieldsSlice();
5382 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len);5388 try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len + body_len + fields_slice.len);
5389 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5383 astgen.extra.appendSliceAssumeCapacity(decls_slice);5390 astgen.extra.appendSliceAssumeCapacity(decls_slice);
5384 astgen.appendBodyWithFixups(body);5391 astgen.appendBodyWithFixups(body);
5385 astgen.extra.appendSliceAssumeCapacity(fields_slice);5392 astgen.extra.appendSliceAssumeCapacity(fields_slice);
53865393
5387 block_scope.unstack();5394 block_scope.unstack();
5388 try gz.addNamespaceCaptures(&namespace);
5389 return decl_inst.toRef();5395 return decl_inst.toRef();
5390}5396}
53915397
...@@ -5555,7 +5561,7 @@ fn containerDecl(...@@ -5555,7 +5561,7 @@ fn containerDecl(
5555 defer block_scope.unstack();5561 defer block_scope.unstack();
55565562
5557 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);5563 _ = try astgen.scanDecls(&namespace, container_decl.ast.members);
5558 namespace.base.tag = .enum_namespace;5564 namespace.base.tag = .namespace;
55595565
5560 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)5566 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
5561 try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg)5567 try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg)
...@@ -5586,7 +5592,6 @@ fn containerDecl(...@@ -5586,7 +5592,6 @@ fn containerDecl(
5586 if (member_node == counts.nonexhaustive_node)5592 if (member_node == counts.nonexhaustive_node)
5587 continue;5593 continue;
5588 fields_hasher.update(tree.getNodeSource(member_node));5594 fields_hasher.update(tree.getNodeSource(member_node));
5589 namespace.base.tag = .namespace;
5590 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {5595 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
5591 .decl => continue,5596 .decl => continue,
5592 .field => |field| field,5597 .field => |field| field,
...@@ -5630,7 +5635,6 @@ fn containerDecl(...@@ -5630,7 +5635,6 @@ fn containerDecl(
5630 },5635 },
5631 );5636 );
5632 }5637 }
5633 namespace.base.tag = .enum_namespace;
5634 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);5638 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
5635 wip_members.appendToField(@intFromEnum(tag_value_inst));5639 wip_members.appendToField(@intFromEnum(tag_value_inst));
5636 }5640 }
...@@ -5676,6 +5680,7 @@ fn containerDecl(...@@ -5676,6 +5680,7 @@ fn containerDecl(
5676 .src_node = node,5680 .src_node = node,
5677 .nonexhaustive = nonexhaustive,5681 .nonexhaustive = nonexhaustive,
5678 .tag_type = arg_inst,5682 .tag_type = arg_inst,
5683 .captures_len = @intCast(namespace.captures.count()),
5679 .body_len = body_len,5684 .body_len = body_len,
5680 .fields_len = @intCast(counts.total_fields),5685 .fields_len = @intCast(counts.total_fields),
5681 .decls_len = @intCast(counts.decls),5686 .decls_len = @intCast(counts.decls),
...@@ -5685,13 +5690,13 @@ fn containerDecl(...@@ -5685,13 +5690,13 @@ fn containerDecl(
5685 wip_members.finishBits(bits_per_field);5690 wip_members.finishBits(bits_per_field);
5686 const decls_slice = wip_members.declsSlice();5691 const decls_slice = wip_members.declsSlice();
5687 const fields_slice = wip_members.fieldsSlice();5692 const fields_slice = wip_members.fieldsSlice();
5688 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len);5693 try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len + body_len + fields_slice.len);
5694 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5689 astgen.extra.appendSliceAssumeCapacity(decls_slice);5695 astgen.extra.appendSliceAssumeCapacity(decls_slice);
5690 astgen.appendBodyWithFixups(body);5696 astgen.appendBodyWithFixups(body);
5691 astgen.extra.appendSliceAssumeCapacity(fields_slice);5697 astgen.extra.appendSliceAssumeCapacity(fields_slice);
56925698
5693 block_scope.unstack();5699 block_scope.unstack();
5694 try gz.addNamespaceCaptures(&namespace);
5695 return rvalue(gz, ri, decl_inst.toRef(), node);5700 return rvalue(gz, ri, decl_inst.toRef(), node);
5696 },5701 },
5697 .keyword_opaque => {5702 .keyword_opaque => {
...@@ -5733,16 +5738,17 @@ fn containerDecl(...@@ -5733,16 +5738,17 @@ fn containerDecl(
57335738
5734 try gz.setOpaque(decl_inst, .{5739 try gz.setOpaque(decl_inst, .{
5735 .src_node = node,5740 .src_node = node,
5741 .captures_len = @intCast(namespace.captures.count()),
5736 .decls_len = decl_count,5742 .decls_len = decl_count,
5737 });5743 });
57385744
5739 wip_members.finishBits(0);5745 wip_members.finishBits(0);
5740 const decls_slice = wip_members.declsSlice();5746 const decls_slice = wip_members.declsSlice();
5741 try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len);5747 try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() + decls_slice.len);
5748 astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys()));
5742 astgen.extra.appendSliceAssumeCapacity(decls_slice);5749 astgen.extra.appendSliceAssumeCapacity(decls_slice);
57435750
5744 block_scope.unstack();5751 block_scope.unstack();
5745 try gz.addNamespaceCaptures(&namespace);
5746 return rvalue(gz, ri, decl_inst.toRef(), node);5752 return rvalue(gz, ri, decl_inst.toRef(), node);
5747 },5753 },
5748 else => unreachable,5754 else => unreachable,
...@@ -8238,12 +8244,12 @@ fn localVarRef(...@@ -8238,12 +8244,12 @@ fn localVarRef(
8238 ident_token: Ast.TokenIndex,8244 ident_token: Ast.TokenIndex,
8239) InnerError!Zir.Inst.Ref {8245) InnerError!Zir.Inst.Ref {
8240 const astgen = gz.astgen;8246 const astgen = gz.astgen;
8241 const gpa = astgen.gpa;
8242 const name_str_index = try astgen.identAsString(ident_token);8247 const name_str_index = try astgen.identAsString(ident_token);
8243 var s = scope;8248 var s = scope;
8244 var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already8249 var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already
8245 var num_namespaces_out: u32 = 0;8250 var num_namespaces_out: u32 = 0;
8246 var capturing_namespace: ?*Scope.Namespace = null;8251 // defined when `num_namespaces_out != 0`
8252 var capturing_namespace: *Scope.Namespace = undefined;
8247 while (true) switch (s.tag) {8253 while (true) switch (s.tag) {
8248 .local_val => {8254 .local_val => {
8249 const local_val = s.cast(Scope.LocalVal).?;8255 const local_val = s.cast(Scope.LocalVal).?;
...@@ -8257,15 +8263,14 @@ fn localVarRef(...@@ -8257,15 +8263,14 @@ fn localVarRef(
8257 local_val.used = ident_token;8263 local_val.used = ident_token;
8258 }8264 }
82598265
8260 const value_inst = try tunnelThroughClosure(8266 const value_inst = if (num_namespaces_out != 0) try tunnelThroughClosure(
8261 gz,8267 gz,
8262 ident,8268 ident,
8263 num_namespaces_out,8269 num_namespaces_out,
8264 capturing_namespace,8270 capturing_namespace,
8265 local_val.inst,8271 local_val.inst,
8266 local_val.token_src,8272 local_val.token_src,
8267 gpa,8273 ) else local_val.inst;
8268 );
82698274
8270 return rvalueNoCoercePreRef(gz, ri, value_inst, ident);8275 return rvalueNoCoercePreRef(gz, ri, value_inst, ident);
8271 }8276 }
...@@ -8285,19 +8290,18 @@ fn localVarRef(...@@ -8285,19 +8290,18 @@ fn localVarRef(
8285 const ident_name = try astgen.identifierTokenString(ident_token);8290 const ident_name = try astgen.identifierTokenString(ident_token);
8286 return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{8291 return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{
8287 try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),8292 try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),
8288 try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}),8293 try astgen.errNoteNode(capturing_namespace.node, "crosses namespace boundary here", .{}),
8289 });8294 });
8290 }8295 }
82918296
8292 const ptr_inst = try tunnelThroughClosure(8297 const ptr_inst = if (num_namespaces_out != 0) try tunnelThroughClosure(
8293 gz,8298 gz,
8294 ident,8299 ident,
8295 num_namespaces_out,8300 num_namespaces_out,
8296 capturing_namespace,8301 capturing_namespace,
8297 local_ptr.ptr,8302 local_ptr.ptr,
8298 local_ptr.token_src,8303 local_ptr.token_src,
8299 gpa,8304 ) else local_ptr.ptr;
8300 );
83018305
8302 switch (ri.rl) {8306 switch (ri.rl) {
8303 .ref, .ref_coerced_ty => {8307 .ref, .ref_coerced_ty => {
...@@ -8314,7 +8318,7 @@ fn localVarRef(...@@ -8314,7 +8318,7 @@ fn localVarRef(
8314 },8318 },
8315 .gen_zir => s = s.cast(GenZir).?.parent,8319 .gen_zir => s = s.cast(GenZir).?.parent,
8316 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,8320 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
8317 .namespace, .enum_namespace => {8321 .namespace => {
8318 const ns = s.cast(Scope.Namespace).?;8322 const ns = s.cast(Scope.Namespace).?;
8319 if (ns.decls.get(name_str_index)) |i| {8323 if (ns.decls.get(name_str_index)) |i| {
8320 if (found_already) |f| {8324 if (found_already) |f| {
...@@ -8326,7 +8330,7 @@ fn localVarRef(...@@ -8326,7 +8330,7 @@ fn localVarRef(
8326 // We found a match but must continue looking for ambiguous references to decls.8330 // We found a match but must continue looking for ambiguous references to decls.
8327 found_already = i;8331 found_already = i;
8328 }8332 }
8329 if (s.tag == .namespace) num_namespaces_out += 1;8333 num_namespaces_out += 1;
8330 capturing_namespace = ns;8334 capturing_namespace = ns;
8331 s = ns.parent;8335 s = ns.parent;
8332 },8336 },
...@@ -8348,41 +8352,70 @@ fn localVarRef(...@@ -8348,41 +8352,70 @@ fn localVarRef(
8348 }8352 }
8349}8353}
83508354
8351/// Adds a capture to a namespace, if needed.8355/// Access a ZIR instruction through closure. May tunnel through arbitrarily
8352/// Returns the index of the closure_capture instruction.8356/// many namespaces, adding closure captures as required.
8357/// Returns the index of the `closure_get` instruction added to `gz`.
8353fn tunnelThroughClosure(8358fn tunnelThroughClosure(
8354 gz: *GenZir,8359 gz: *GenZir,
8360 /// The node which references the value to be captured.
8355 inner_ref_node: Ast.Node.Index,8361 inner_ref_node: Ast.Node.Index,
8362 /// The number of namespaces being tunnelled through. At least 1.
8356 num_tunnels: u32,8363 num_tunnels: u32,
8357 ns: ?*Scope.Namespace,8364 /// The namespace being captured from.
8365 ns: *Scope.Namespace,
8366 /// The value being captured.
8358 value: Zir.Inst.Ref,8367 value: Zir.Inst.Ref,
8368 /// The token of the value's declaration.
8359 token: Ast.TokenIndex,8369 token: Ast.TokenIndex,
8360 gpa: Allocator,
8361) !Zir.Inst.Ref {8370) !Zir.Inst.Ref {
8362 // For trivial values, we don't need a tunnel.8371 const value_inst = value.toIndex() orelse {
8363 // Just return the ref.8372 // For trivial values, we don't need a tunnel; just return the ref.
8364 if (num_tunnels == 0 or value.toIndex() == null) {
8365 return value;8373 return value;
8374 };
8375
8376 const astgen = gz.astgen;
8377 const gpa = astgen.gpa;
8378
8379 // Otherwise we need a tunnel. First, figure out the path of namespaces we
8380 // are tunneling through. This is usually only going to be one or two, so
8381 // use an SFBA to optimize for the common case.
8382 var sfba = std.heap.stackFallback(@sizeOf(usize) * 2, astgen.arena);
8383 var intermediate_tunnels = try sfba.get().alloc(*Scope.Namespace, num_tunnels - 1);
8384
8385 {
8386 var i: usize = num_tunnels - 1;
8387 var scope: *Scope = gz.parent;
8388 while (i > 0) {
8389 if (scope.cast(Scope.Namespace)) |mid_ns| {
8390 i -= 1;
8391 intermediate_tunnels[i] = mid_ns;
8392 }
8393 scope = scope.parent().?;
8394 }
8366 }8395 }
83678396
8368 // Otherwise we need a tunnel. Check if this namespace8397 // Now that we know the scopes we're tunneling through, begin adding
8369 // already has one for this value.8398 // captures as required, starting with the outermost namespace.
8370 const gop = try ns.?.captures.getOrPut(gpa, value.toIndex().?);8399 var cur_capture_index = std.math.cast(
8371 if (!gop.found_existing) {8400 u16,
8372 // Make a new capture for this value but don't add it to the declaring_gz yet8401 (try ns.captures.getOrPut(gpa, Zir.Inst.Capture.wrap(.{ .inst = value_inst }))).index,
8373 try gz.astgen.instructions.append(gz.astgen.gpa, .{8402 ) orelse return astgen.failNodeNotes(ns.node, "this compiler implementation only supports up to 65536 captures per namespace", .{}, &.{
8374 .tag = .closure_capture,8403 try astgen.errNoteTok(token, "captured value here", .{}),
8375 .data = .{ .un_tok = .{8404 try astgen.errNoteNode(inner_ref_node, "value used here", .{}),
8376 .operand = value,8405 });
8377 .src_tok = ns.?.declaring_gz.?.tokenIndexToRelative(token),8406
8378 } },8407 for (intermediate_tunnels) |tunnel_ns| {
8408 cur_capture_index = std.math.cast(
8409 u16,
8410 (try tunnel_ns.captures.getOrPut(gpa, Zir.Inst.Capture.wrap(.{ .nested = cur_capture_index }))).index,
8411 ) orelse return astgen.failNodeNotes(tunnel_ns.node, "this compiler implementation only supports up to 65536 captures per namespace", .{}, &.{
8412 try astgen.errNoteTok(token, "captured value here", .{}),
8413 try astgen.errNoteNode(inner_ref_node, "value used here", .{}),
8379 });8414 });
8380 gop.value_ptr.* = @enumFromInt(gz.astgen.instructions.len - 1);
8381 }8415 }
83828416
8383 // Add an instruction to get the value from the closure into8417 // Add an instruction to get the value from the closure.
8384 // our current context8418 return gz.addExtendedNodeSmall(.closure_get, inner_ref_node, cur_capture_index);
8385 return try gz.addInstNode(.closure_get, gop.value_ptr.*, inner_ref_node);
8386}8419}
83878420
8388fn stringLiteral(8421fn stringLiteral(
...@@ -9095,7 +9128,7 @@ fn builtinCall(...@@ -9095,7 +9128,7 @@ fn builtinCall(
9095 },9128 },
9096 .gen_zir => s = s.cast(GenZir).?.parent,9129 .gen_zir => s = s.cast(GenZir).?.parent,
9097 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,9130 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
9098 .namespace, .enum_namespace => {9131 .namespace => {
9099 const ns = s.cast(Scope.Namespace).?;9132 const ns = s.cast(Scope.Namespace).?;
9100 if (ns.decls.get(decl_name)) |i| {9133 if (ns.decls.get(decl_name)) |i| {
9101 if (found_already) |f| {9134 if (found_already) |f| {
...@@ -11605,7 +11638,7 @@ const Scope = struct {...@@ -11605,7 +11638,7 @@ const Scope = struct {
11605 }11638 }
11606 if (T == Namespace) {11639 if (T == Namespace) {
11607 switch (base.tag) {11640 switch (base.tag) {
11608 .namespace, .enum_namespace => return @fieldParentPtr(T, "base", base),11641 .namespace => return @fieldParentPtr(T, "base", base),
11609 else => return null,11642 else => return null,
11610 }11643 }
11611 }11644 }
...@@ -11621,7 +11654,7 @@ const Scope = struct {...@@ -11621,7 +11654,7 @@ const Scope = struct {
11621 .local_val => base.cast(LocalVal).?.parent,11654 .local_val => base.cast(LocalVal).?.parent,
11622 .local_ptr => base.cast(LocalPtr).?.parent,11655 .local_ptr => base.cast(LocalPtr).?.parent,
11623 .defer_normal, .defer_error => base.cast(Defer).?.parent,11656 .defer_normal, .defer_error => base.cast(Defer).?.parent,
11624 .namespace, .enum_namespace => base.cast(Namespace).?.parent,11657 .namespace => base.cast(Namespace).?.parent,
11625 .top => null,11658 .top => null,
11626 };11659 };
11627 }11660 }
...@@ -11633,7 +11666,6 @@ const Scope = struct {...@@ -11633,7 +11666,6 @@ const Scope = struct {
11633 defer_normal,11666 defer_normal,
11634 defer_error,11667 defer_error,
11635 namespace,11668 namespace,
11636 enum_namespace,
11637 top,11669 top,
11638 };11670 };
1163911671
...@@ -11725,9 +11757,8 @@ const Scope = struct {...@@ -11725,9 +11757,8 @@ const Scope = struct {
11725 /// Only valid during astgen.11757 /// Only valid during astgen.
11726 declaring_gz: ?*GenZir,11758 declaring_gz: ?*GenZir,
1172711759
11728 /// Map from the raw captured value to the instruction11760 /// Set of captures used by this namespace.
11729 /// ref of the capture for decls in this namespace11761 captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Capture, void) = .{},
11730 captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
1173111762
11732 fn deinit(self: *Namespace, gpa: Allocator) void {11763 fn deinit(self: *Namespace, gpa: Allocator) void {
11733 self.decls.deinit(gpa);11764 self.decls.deinit(gpa);
...@@ -11787,12 +11818,6 @@ const GenZir = struct {...@@ -11787,12 +11818,6 @@ const GenZir = struct {
11787 // Set if this GenZir is a defer or it is inside a defer.11818 // Set if this GenZir is a defer or it is inside a defer.
11788 any_defer_node: Ast.Node.Index = 0,11819 any_defer_node: Ast.Node.Index = 0,
1178911820
11790 /// Namespace members are lazy. When executing a decl within a namespace,
11791 /// any references to external instructions need to be treated specially.
11792 /// This list tracks those references. See also .closure_capture and .closure_get.
11793 /// Keys are the raw instruction index, values are the closure_capture instruction.
11794 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
11795
11796 const unstacked_top = std.math.maxInt(usize);11821 const unstacked_top = std.math.maxInt(usize);
11797 /// Call unstack before adding any new instructions to containing GenZir.11822 /// Call unstack before adding any new instructions to containing GenZir.
11798 fn unstack(self: *GenZir) void {11823 fn unstack(self: *GenZir) void {
...@@ -12534,6 +12559,30 @@ const GenZir = struct {...@@ -12534,6 +12559,30 @@ const GenZir = struct {
12534 return new_index.toRef();12559 return new_index.toRef();
12535 }12560 }
1253612561
12562 fn addExtendedNodeSmall(
12563 gz: *GenZir,
12564 opcode: Zir.Inst.Extended,
12565 src_node: Ast.Node.Index,
12566 small: u16,
12567 ) !Zir.Inst.Ref {
12568 const astgen = gz.astgen;
12569 const gpa = astgen.gpa;
12570
12571 try gz.instructions.ensureUnusedCapacity(gpa, 1);
12572 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
12573 const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
12574 astgen.instructions.appendAssumeCapacity(.{
12575 .tag = .extended,
12576 .data = .{ .extended = .{
12577 .opcode = opcode,
12578 .small = small,
12579 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),
12580 } },
12581 });
12582 gz.instructions.appendAssumeCapacity(new_index);
12583 return new_index.toRef();
12584 }
12585
12537 fn addUnTok(12586 fn addUnTok(
12538 gz: *GenZir,12587 gz: *GenZir,
12539 tag: Zir.Inst.Tag,12588 tag: Zir.Inst.Tag,
...@@ -12957,10 +13006,10 @@ const GenZir = struct {...@@ -12957,10 +13006,10 @@ const GenZir = struct {
1295713006
12958 fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct {13007 fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
12959 src_node: Ast.Node.Index,13008 src_node: Ast.Node.Index,
13009 captures_len: u32,
12960 fields_len: u32,13010 fields_len: u32,
12961 decls_len: u32,13011 decls_len: u32,
12962 backing_int_ref: Zir.Inst.Ref,13012 has_backing_int: bool,
12963 backing_int_body_len: u32,
12964 layout: std.builtin.Type.ContainerLayout,13013 layout: std.builtin.Type.ContainerLayout,
12965 known_non_opv: bool,13014 known_non_opv: bool,
12966 known_comptime_only: bool,13015 known_comptime_only: bool,
...@@ -12978,7 +13027,7 @@ const GenZir = struct {...@@ -12978,7 +13027,7 @@ const GenZir = struct {
1297813027
12979 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13028 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1298013029
12981 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 4);13030 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len + 3);
12982 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{13031 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{
12983 .fields_hash_0 = fields_hash_arr[0],13032 .fields_hash_0 = fields_hash_arr[0],
12984 .fields_hash_1 = fields_hash_arr[1],13033 .fields_hash_1 = fields_hash_arr[1],
...@@ -12987,26 +13036,24 @@ const GenZir = struct {...@@ -12987,26 +13036,24 @@ const GenZir = struct {
12987 .src_node = gz.nodeIndexToRelative(args.src_node),13036 .src_node = gz.nodeIndexToRelative(args.src_node),
12988 });13037 });
1298913038
13039 if (args.captures_len != 0) {
13040 astgen.extra.appendAssumeCapacity(args.captures_len);
13041 }
12990 if (args.fields_len != 0) {13042 if (args.fields_len != 0) {
12991 astgen.extra.appendAssumeCapacity(args.fields_len);13043 astgen.extra.appendAssumeCapacity(args.fields_len);
12992 }13044 }
12993 if (args.decls_len != 0) {13045 if (args.decls_len != 0) {
12994 astgen.extra.appendAssumeCapacity(args.decls_len);13046 astgen.extra.appendAssumeCapacity(args.decls_len);
12995 }13047 }
12996 if (args.backing_int_ref != .none) {
12997 astgen.extra.appendAssumeCapacity(args.backing_int_body_len);
12998 if (args.backing_int_body_len == 0) {
12999 astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_ref));
13000 }
13001 }
13002 astgen.instructions.set(@intFromEnum(inst), .{13048 astgen.instructions.set(@intFromEnum(inst), .{
13003 .tag = .extended,13049 .tag = .extended,
13004 .data = .{ .extended = .{13050 .data = .{ .extended = .{
13005 .opcode = .struct_decl,13051 .opcode = .struct_decl,
13006 .small = @bitCast(Zir.Inst.StructDecl.Small{13052 .small = @bitCast(Zir.Inst.StructDecl.Small{
13053 .has_captures_len = args.captures_len != 0,
13007 .has_fields_len = args.fields_len != 0,13054 .has_fields_len = args.fields_len != 0,
13008 .has_decls_len = args.decls_len != 0,13055 .has_decls_len = args.decls_len != 0,
13009 .has_backing_int = args.backing_int_ref != .none,13056 .has_backing_int = args.has_backing_int,
13010 .known_non_opv = args.known_non_opv,13057 .known_non_opv = args.known_non_opv,
13011 .known_comptime_only = args.known_comptime_only,13058 .known_comptime_only = args.known_comptime_only,
13012 .is_tuple = args.is_tuple,13059 .is_tuple = args.is_tuple,
...@@ -13024,6 +13071,7 @@ const GenZir = struct {...@@ -13024,6 +13071,7 @@ const GenZir = struct {
13024 fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct {13071 fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
13025 src_node: Ast.Node.Index,13072 src_node: Ast.Node.Index,
13026 tag_type: Zir.Inst.Ref,13073 tag_type: Zir.Inst.Ref,
13074 captures_len: u32,
13027 body_len: u32,13075 body_len: u32,
13028 fields_len: u32,13076 fields_len: u32,
13029 decls_len: u32,13077 decls_len: u32,
...@@ -13039,7 +13087,7 @@ const GenZir = struct {...@@ -13039,7 +13087,7 @@ const GenZir = struct {
1303913087
13040 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13088 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1304113089
13042 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 4);13090 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).Struct.fields.len + 5);
13043 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{13091 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{
13044 .fields_hash_0 = fields_hash_arr[0],13092 .fields_hash_0 = fields_hash_arr[0],
13045 .fields_hash_1 = fields_hash_arr[1],13093 .fields_hash_1 = fields_hash_arr[1],
...@@ -13051,6 +13099,9 @@ const GenZir = struct {...@@ -13051,6 +13099,9 @@ const GenZir = struct {
13051 if (args.tag_type != .none) {13099 if (args.tag_type != .none) {
13052 astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type));13100 astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type));
13053 }13101 }
13102 if (args.captures_len != 0) {
13103 astgen.extra.appendAssumeCapacity(args.captures_len);
13104 }
13054 if (args.body_len != 0) {13105 if (args.body_len != 0) {
13055 astgen.extra.appendAssumeCapacity(args.body_len);13106 astgen.extra.appendAssumeCapacity(args.body_len);
13056 }13107 }
...@@ -13066,6 +13117,7 @@ const GenZir = struct {...@@ -13066,6 +13117,7 @@ const GenZir = struct {
13066 .opcode = .union_decl,13117 .opcode = .union_decl,
13067 .small = @bitCast(Zir.Inst.UnionDecl.Small{13118 .small = @bitCast(Zir.Inst.UnionDecl.Small{
13068 .has_tag_type = args.tag_type != .none,13119 .has_tag_type = args.tag_type != .none,
13120 .has_captures_len = args.captures_len != 0,
13069 .has_body_len = args.body_len != 0,13121 .has_body_len = args.body_len != 0,
13070 .has_fields_len = args.fields_len != 0,13122 .has_fields_len = args.fields_len != 0,
13071 .has_decls_len = args.decls_len != 0,13123 .has_decls_len = args.decls_len != 0,
...@@ -13082,6 +13134,7 @@ const GenZir = struct {...@@ -13082,6 +13134,7 @@ const GenZir = struct {
13082 fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct {13134 fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
13083 src_node: Ast.Node.Index,13135 src_node: Ast.Node.Index,
13084 tag_type: Zir.Inst.Ref,13136 tag_type: Zir.Inst.Ref,
13137 captures_len: u32,
13085 body_len: u32,13138 body_len: u32,
13086 fields_len: u32,13139 fields_len: u32,
13087 decls_len: u32,13140 decls_len: u32,
...@@ -13095,7 +13148,7 @@ const GenZir = struct {...@@ -13095,7 +13148,7 @@ const GenZir = struct {
1309513148
13096 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13149 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1309713150
13098 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 4);13151 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len + 5);
13099 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{13152 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
13100 .fields_hash_0 = fields_hash_arr[0],13153 .fields_hash_0 = fields_hash_arr[0],
13101 .fields_hash_1 = fields_hash_arr[1],13154 .fields_hash_1 = fields_hash_arr[1],
...@@ -13107,6 +13160,9 @@ const GenZir = struct {...@@ -13107,6 +13160,9 @@ const GenZir = struct {
13107 if (args.tag_type != .none) {13160 if (args.tag_type != .none) {
13108 astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type));13161 astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type));
13109 }13162 }
13163 if (args.captures_len != 0) {
13164 astgen.extra.appendAssumeCapacity(args.captures_len);
13165 }
13110 if (args.body_len != 0) {13166 if (args.body_len != 0) {
13111 astgen.extra.appendAssumeCapacity(args.body_len);13167 astgen.extra.appendAssumeCapacity(args.body_len);
13112 }13168 }
...@@ -13122,6 +13178,7 @@ const GenZir = struct {...@@ -13122,6 +13178,7 @@ const GenZir = struct {
13122 .opcode = .enum_decl,13178 .opcode = .enum_decl,
13123 .small = @bitCast(Zir.Inst.EnumDecl.Small{13179 .small = @bitCast(Zir.Inst.EnumDecl.Small{
13124 .has_tag_type = args.tag_type != .none,13180 .has_tag_type = args.tag_type != .none,
13181 .has_captures_len = args.captures_len != 0,
13125 .has_body_len = args.body_len != 0,13182 .has_body_len = args.body_len != 0,
13126 .has_fields_len = args.fields_len != 0,13183 .has_fields_len = args.fields_len != 0,
13127 .has_decls_len = args.decls_len != 0,13184 .has_decls_len = args.decls_len != 0,
...@@ -13135,6 +13192,7 @@ const GenZir = struct {...@@ -13135,6 +13192,7 @@ const GenZir = struct {
1313513192
13136 fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct {13193 fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct {
13137 src_node: Ast.Node.Index,13194 src_node: Ast.Node.Index,
13195 captures_len: u32,
13138 decls_len: u32,13196 decls_len: u32,
13139 }) !void {13197 }) !void {
13140 const astgen = gz.astgen;13198 const astgen = gz.astgen;
...@@ -13142,11 +13200,14 @@ const GenZir = struct {...@@ -13142,11 +13200,14 @@ const GenZir = struct {
1314213200
13143 assert(args.src_node != 0);13201 assert(args.src_node != 0);
1314413202
13145 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 1);13203 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len + 2);
13146 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{13204 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
13147 .src_node = gz.nodeIndexToRelative(args.src_node),13205 .src_node = gz.nodeIndexToRelative(args.src_node),
13148 });13206 });
1314913207
13208 if (args.captures_len != 0) {
13209 astgen.extra.appendAssumeCapacity(args.captures_len);
13210 }
13150 if (args.decls_len != 0) {13211 if (args.decls_len != 0) {
13151 astgen.extra.appendAssumeCapacity(args.decls_len);13212 astgen.extra.appendAssumeCapacity(args.decls_len);
13152 }13213 }
...@@ -13155,6 +13216,7 @@ const GenZir = struct {...@@ -13155,6 +13216,7 @@ const GenZir = struct {
13155 .data = .{ .extended = .{13216 .data = .{ .extended = .{
13156 .opcode = .opaque_decl,13217 .opcode = .opaque_decl,
13157 .small = @bitCast(Zir.Inst.OpaqueDecl.Small{13218 .small = @bitCast(Zir.Inst.OpaqueDecl.Small{
13219 .has_captures_len = args.captures_len != 0,
13158 .has_decls_len = args.decls_len != 0,13220 .has_decls_len = args.decls_len != 0,
13159 .name_strategy = gz.anon_name_strategy,13221 .name_strategy = gz.anon_name_strategy,
13160 }),13222 }),
...@@ -13197,15 +13259,6 @@ const GenZir = struct {...@@ -13197,15 +13259,6 @@ const GenZir = struct {
13197 }13259 }
13198 }13260 }
1319913261
13200 fn addNamespaceCaptures(gz: *GenZir, namespace: *Scope.Namespace) !void {
13201 if (namespace.captures.count() > 0) {
13202 try gz.instructions.ensureUnusedCapacity(gz.astgen.gpa, namespace.captures.count());
13203 for (namespace.captures.values()) |capture| {
13204 gz.instructions.appendAssumeCapacity(capture);
13205 }
13206 }
13207 }
13208
13209 fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: Zir.NullTerminatedString, inst: Zir.Inst.Ref) !void {13262 fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: Zir.NullTerminatedString, inst: Zir.Inst.Ref) !void {
13210 if (gz.is_comptime) return;13263 if (gz.is_comptime) return;
1321113264
...@@ -13305,7 +13358,7 @@ fn detectLocalShadowing(...@@ -13305,7 +13358,7 @@ fn detectLocalShadowing(
13305 }13358 }
13306 s = local_ptr.parent;13359 s = local_ptr.parent;
13307 },13360 },
13308 .namespace, .enum_namespace => {13361 .namespace => {
13309 outer_scope = true;13362 outer_scope = true;
13310 const ns = s.cast(Scope.Namespace).?;13363 const ns = s.cast(Scope.Namespace).?;
13311 const decl_node = ns.decls.get(ident_name) orelse {13364 const decl_node = ns.decls.get(ident_name) orelse {
...@@ -13478,7 +13531,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -13478,7 +13531,7 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
13478 }13531 }
13479 s = local_ptr.parent;13532 s = local_ptr.parent;
13480 },13533 },
13481 .namespace, .enum_namespace => s = s.cast(Scope.Namespace).?.parent,13534 .namespace => s = s.cast(Scope.Namespace).?.parent,
13482 .gen_zir => s = s.cast(GenZir).?.parent,13535 .gen_zir => s = s.cast(GenZir).?.parent,
13483 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,13536 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
13484 .top => break,13537 .top => break,
lib/std/zig/Zir.zig+99-48
...@@ -1004,17 +1004,6 @@ pub const Inst = struct {...@@ -1004,17 +1004,6 @@ pub const Inst = struct {
1004 @"resume",1004 @"resume",
1005 @"await",1005 @"await",
10061006
1007 /// When a type or function refers to a comptime value from an outer
1008 /// scope, that forms a closure over comptime value. The outer scope
1009 /// will record a capture of that value, which encodes its current state
1010 /// and marks it to persist. Uses `un_tok` field. Operand is the
1011 /// instruction value to capture.
1012 closure_capture,
1013 /// The inner scope of a closure uses closure_get to retrieve the value
1014 /// stored by the outer scope. Uses `inst_node` field. Operand is the
1015 /// closure_capture instruction ref.
1016 closure_get,
1017
1018 /// A defer statement.1007 /// A defer statement.
1019 /// Uses the `defer` union field.1008 /// Uses the `defer` union field.
1020 @"defer",1009 @"defer",
...@@ -1251,8 +1240,6 @@ pub const Inst = struct {...@@ -1251,8 +1240,6 @@ pub const Inst = struct {
1251 .@"await",1240 .@"await",
1252 .ret_err_value_code,1241 .ret_err_value_code,
1253 .extended,1242 .extended,
1254 .closure_get,
1255 .closure_capture,
1256 .ret_ptr,1243 .ret_ptr,
1257 .ret_type,1244 .ret_type,
1258 .@"try",1245 .@"try",
...@@ -1542,8 +1529,6 @@ pub const Inst = struct {...@@ -1542,8 +1529,6 @@ pub const Inst = struct {
1542 .@"resume",1529 .@"resume",
1543 .@"await",1530 .@"await",
1544 .ret_err_value_code,1531 .ret_err_value_code,
1545 .closure_get,
1546 .closure_capture,
1547 .@"break",1532 .@"break",
1548 .break_inline,1533 .break_inline,
1549 .condbr,1534 .condbr,
...@@ -1829,9 +1814,6 @@ pub const Inst = struct {...@@ -1829,9 +1814,6 @@ pub const Inst = struct {
1829 .@"resume" = .un_node,1814 .@"resume" = .un_node,
1830 .@"await" = .un_node,1815 .@"await" = .un_node,
18311816
1832 .closure_capture = .un_tok,
1833 .closure_get = .inst_node,
1834
1835 .@"defer" = .@"defer",1817 .@"defer" = .@"defer",
1836 .defer_err_code = .defer_err_code,1818 .defer_err_code = .defer_err_code,
18371819
...@@ -2074,6 +2056,10 @@ pub const Inst = struct {...@@ -2074,6 +2056,10 @@ pub const Inst = struct {
2074 /// `operand` is payload index to `RestoreErrRetIndex`.2056 /// `operand` is payload index to `RestoreErrRetIndex`.
2075 /// `small` is undefined.2057 /// `small` is undefined.
2076 restore_err_ret_index,2058 restore_err_ret_index,
2059 /// Retrieves a value from the current type declaration scope's closure.
2060 /// `operand` is `src_node: i32`.
2061 /// `small` is closure index.
2062 closure_get,
2077 /// Used as a placeholder instruction which is just a dummy index for Sema to replace2063 /// Used as a placeholder instruction which is just a dummy index for Sema to replace
2078 /// with a specific value. For instance, this is used for the capture of an `errdefer`.2064 /// with a specific value. For instance, this is used for the capture of an `errdefer`.
2079 /// This should never appear in a body.2065 /// This should never appear in a body.
...@@ -2949,7 +2935,7 @@ pub const Inst = struct {...@@ -2949,7 +2935,7 @@ pub const Inst = struct {
2949 /// These are stored in trailing data in `extra` for each prong.2935 /// These are stored in trailing data in `extra` for each prong.
2950 pub const ProngInfo = packed struct(u32) {2936 pub const ProngInfo = packed struct(u32) {
2951 body_len: u28,2937 body_len: u28,
2952 capture: Capture,2938 capture: ProngInfo.Capture,
2953 is_inline: bool,2939 is_inline: bool,
2954 has_tag_capture: bool,2940 has_tag_capture: bool,
29552941
...@@ -3013,19 +2999,21 @@ pub const Inst = struct {...@@ -3013,19 +2999,21 @@ pub const Inst = struct {
3013 };2999 };
30143000
3015 /// Trailing:3001 /// Trailing:
3016 /// 0. fields_len: u32, // if has_fields_len3002 /// 0. captures_len: u32 // if has_captures_len
3017 /// 1. decls_len: u32, // if has_decls_len3003 /// 1. fields_len: u32, // if has_fields_len
3018 /// 2. backing_int_body_len: u32, // if has_backing_int3004 /// 2. decls_len: u32, // if has_decls_len
3019 /// 3. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 03005 /// 3. capture: Capture // for every captures_len
3020 /// 4. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 03006 /// 4. backing_int_body_len: u32, // if has_backing_int
3021 /// 5. decl: Index, // for every decls_len; points to a `declaration` instruction3007 /// 5. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0
3022 /// 6. flags: u32 // for every 8 fields3008 /// 6. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0
3009 /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction
3010 /// 8. flags: u32 // for every 8 fields
3023 /// - sets of 4 bits:3011 /// - sets of 4 bits:
3024 /// 0b000X: whether corresponding field has an align expression3012 /// 0b000X: whether corresponding field has an align expression
3025 /// 0b00X0: whether corresponding field has a default expression3013 /// 0b00X0: whether corresponding field has a default expression
3026 /// 0b0X00: whether corresponding field is comptime3014 /// 0b0X00: whether corresponding field is comptime
3027 /// 0bX000: whether corresponding field has a type expression3015 /// 0bX000: whether corresponding field has a type expression
3028 /// 7. fields: { // for every fields_len3016 /// 9. fields: { // for every fields_len
3029 /// field_name: u32, // if !is_tuple3017 /// field_name: u32, // if !is_tuple
3030 /// doc_comment: NullTerminatedString, // .empty if no doc comment3018 /// doc_comment: NullTerminatedString, // .empty if no doc comment
3031 /// field_type: Ref, // if corresponding bit is not set. none means anytype.3019 /// field_type: Ref, // if corresponding bit is not set. none means anytype.
...@@ -3033,7 +3021,7 @@ pub const Inst = struct {...@@ -3033,7 +3021,7 @@ pub const Inst = struct {
3033 /// align_body_len: u32, // if corresponding bit is set3021 /// align_body_len: u32, // if corresponding bit is set
3034 /// init_body_len: u32, // if corresponding bit is set3022 /// init_body_len: u32, // if corresponding bit is set
3035 /// }3023 /// }
3036 /// 8. bodies: { // for every fields_len3024 /// 10. bodies: { // for every fields_len
3037 /// field_type_body_inst: Inst, // for each field_type_body_len3025 /// field_type_body_inst: Inst, // for each field_type_body_len
3038 /// align_body_inst: Inst, // for each align_body_len3026 /// align_body_inst: Inst, // for each align_body_len
3039 /// init_body_inst: Inst, // for each init_body_len3027 /// init_body_inst: Inst, // for each init_body_len
...@@ -3052,6 +3040,7 @@ pub const Inst = struct {...@@ -3052,6 +3040,7 @@ pub const Inst = struct {
3052 }3040 }
30533041
3054 pub const Small = packed struct {3042 pub const Small = packed struct {
3043 has_captures_len: bool,
3055 has_fields_len: bool,3044 has_fields_len: bool,
3056 has_decls_len: bool,3045 has_decls_len: bool,
3057 has_backing_int: bool,3046 has_backing_int: bool,
...@@ -3063,10 +3052,35 @@ pub const Inst = struct {...@@ -3063,10 +3052,35 @@ pub const Inst = struct {
3063 any_default_inits: bool,3052 any_default_inits: bool,
3064 any_comptime_fields: bool,3053 any_comptime_fields: bool,
3065 any_aligned_fields: bool,3054 any_aligned_fields: bool,
3066 _: u3 = undefined,3055 _: u2 = undefined,
3067 };3056 };
3068 };3057 };
30693058
3059 /// Represents a single value being captured in a type declaration's closure.
3060 /// If high bit is 0, this represents a `Zir.Inst,Index`.
3061 /// If high bit is 1, this represents an index into the last closure.
3062 pub const Capture = enum(u32) {
3063 _,
3064 pub const Unwrapped = union(enum) {
3065 inst: Zir.Inst.Index,
3066 nested: u16,
3067 };
3068 pub fn wrap(cap: Unwrapped) Capture {
3069 return switch (cap) {
3070 .inst => |inst| @enumFromInt(@intFromEnum(inst)),
3071 .nested => |idx| @enumFromInt((1 << 31) | @as(u32, idx)),
3072 };
3073 }
3074 pub fn unwrap(cap: Capture) Unwrapped {
3075 const raw = @intFromEnum(cap);
3076 const tag: u1 = @intCast(raw >> 31);
3077 return switch (tag) {
3078 0 => .{ .inst = @enumFromInt(raw) },
3079 1 => .{ .nested = @truncate(raw) },
3080 };
3081 }
3082 };
3083
3070 pub const NameStrategy = enum(u2) {3084 pub const NameStrategy = enum(u2) {
3071 /// Use the same name as the parent declaration name.3085 /// Use the same name as the parent declaration name.
3072 /// e.g. `const Foo = struct {...};`.3086 /// e.g. `const Foo = struct {...};`.
...@@ -3098,14 +3112,16 @@ pub const Inst = struct {...@@ -3098,14 +3112,16 @@ pub const Inst = struct {
30983112
3099 /// Trailing:3113 /// Trailing:
3100 /// 0. tag_type: Ref, // if has_tag_type3114 /// 0. tag_type: Ref, // if has_tag_type
3101 /// 1. body_len: u32, // if has_body_len3115 /// 1. captures_len: u32, // if has_captures_len
3102 /// 2. fields_len: u32, // if has_fields_len3116 /// 2. body_len: u32, // if has_body_len
3103 /// 3. decls_len: u32, // if has_decls_len3117 /// 3. fields_len: u32, // if has_fields_len
3104 /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction3118 /// 4. decls_len: u32, // if has_decls_len
3105 /// 5. inst: Index // for every body_len3119 /// 5. capture: Capture // for every captures_len
3106 /// 6. has_bits: u32 // for every 32 fields3120 /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction
3121 /// 7. inst: Index // for every body_len
3122 /// 8. has_bits: u32 // for every 32 fields
3107 /// - the bit is whether corresponding field has an value expression3123 /// - the bit is whether corresponding field has an value expression
3108 /// 7. fields: { // for every fields_len3124 /// 9. fields: { // for every fields_len
3109 /// field_name: u32,3125 /// field_name: u32,
3110 /// doc_comment: u32, // .empty if no doc_comment3126 /// doc_comment: u32, // .empty if no doc_comment
3111 /// value: Ref, // if corresponding bit is set3127 /// value: Ref, // if corresponding bit is set
...@@ -3125,29 +3141,32 @@ pub const Inst = struct {...@@ -3125,29 +3141,32 @@ pub const Inst = struct {
31253141
3126 pub const Small = packed struct {3142 pub const Small = packed struct {
3127 has_tag_type: bool,3143 has_tag_type: bool,
3144 has_captures_len: bool,
3128 has_body_len: bool,3145 has_body_len: bool,
3129 has_fields_len: bool,3146 has_fields_len: bool,
3130 has_decls_len: bool,3147 has_decls_len: bool,
3131 name_strategy: NameStrategy,3148 name_strategy: NameStrategy,
3132 nonexhaustive: bool,3149 nonexhaustive: bool,
3133 _: u9 = undefined,3150 _: u8 = undefined,
3134 };3151 };
3135 };3152 };
31363153
3137 /// Trailing:3154 /// Trailing:
3138 /// 0. tag_type: Ref, // if has_tag_type3155 /// 0. tag_type: Ref, // if has_tag_type
3139 /// 1. body_len: u32, // if has_body_len3156 /// 1. captures_len: u32 // if has_captures_len
3140 /// 2. fields_len: u32, // if has_fields_len3157 /// 2. body_len: u32, // if has_body_len
3141 /// 3. decls_len: u32, // if has_decls_len3158 /// 3. fields_len: u32, // if has_fields_len
3142 /// 4. decl: Index, // for every decls_len; points to a `declaration` instruction3159 /// 4. decls_len: u37, // if has_decls_len
3143 /// 5. inst: Index // for every body_len3160 /// 5. capture: Capture // for every captures_len
3144 /// 6. has_bits: u32 // for every 8 fields3161 /// 6. decl: Index, // for every decls_len; points to a `declaration` instruction
3162 /// 7. inst: Index // for every body_len
3163 /// 8. has_bits: u32 // for every 8 fields
3145 /// - sets of 4 bits:3164 /// - sets of 4 bits:
3146 /// 0b000X: whether corresponding field has a type expression3165 /// 0b000X: whether corresponding field has a type expression
3147 /// 0b00X0: whether corresponding field has a align expression3166 /// 0b00X0: whether corresponding field has a align expression
3148 /// 0b0X00: whether corresponding field has a tag value expression3167 /// 0b0X00: whether corresponding field has a tag value expression
3149 /// 0bX000: unused3168 /// 0bX000: unused
3150 /// 7. fields: { // for every fields_len3169 /// 9. fields: { // for every fields_len
3151 /// field_name: NullTerminatedString, // null terminated string index3170 /// field_name: NullTerminatedString, // null terminated string index
3152 /// doc_comment: NullTerminatedString, // .empty if no doc comment3171 /// doc_comment: NullTerminatedString, // .empty if no doc comment
3153 /// field_type: Ref, // if corresponding bit is set3172 /// field_type: Ref, // if corresponding bit is set
...@@ -3170,6 +3189,7 @@ pub const Inst = struct {...@@ -3170,6 +3189,7 @@ pub const Inst = struct {
31703189
3171 pub const Small = packed struct {3190 pub const Small = packed struct {
3172 has_tag_type: bool,3191 has_tag_type: bool,
3192 has_captures_len: bool,
3173 has_body_len: bool,3193 has_body_len: bool,
3174 has_fields_len: bool,3194 has_fields_len: bool,
3175 has_decls_len: bool,3195 has_decls_len: bool,
...@@ -3183,13 +3203,15 @@ pub const Inst = struct {...@@ -3183,13 +3203,15 @@ pub const Inst = struct {
3183 /// true | false | union(T) { }3203 /// true | false | union(T) { }
3184 auto_enum_tag: bool,3204 auto_enum_tag: bool,
3185 any_aligned_fields: bool,3205 any_aligned_fields: bool,
3186 _: u6 = undefined,3206 _: u5 = undefined,
3187 };3207 };
3188 };3208 };
31893209
3190 /// Trailing:3210 /// Trailing:
3191 /// 0. decls_len: u32, // if has_decls_len3211 /// 0. captures_len: u32, // if has_captures_len
3192 /// 1. decl: Index, // for every decls_len; points to a `declaration` instruction3212 /// 1. decls_len: u32, // if has_decls_len
3213 /// 2. capture: Capture, // for every captures_len
3214 /// 3. decl: Index, // for every decls_len; points to a `declaration` instruction
3193 pub const OpaqueDecl = struct {3215 pub const OpaqueDecl = struct {
3194 src_node: i32,3216 src_node: i32,
31953217
...@@ -3198,9 +3220,10 @@ pub const Inst = struct {...@@ -3198,9 +3220,10 @@ pub const Inst = struct {
3198 }3220 }
31993221
3200 pub const Small = packed struct {3222 pub const Small = packed struct {
3223 has_captures_len: bool,
3201 has_decls_len: bool,3224 has_decls_len: bool,
3202 name_strategy: NameStrategy,3225 name_strategy: NameStrategy,
3203 _: u13 = undefined,3226 _: u12 = undefined,
3204 };3227 };
3205 };3228 };
32063229
...@@ -3502,6 +3525,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3502,6 +3525,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3502 .struct_decl => {3525 .struct_decl => {
3503 const small: Inst.StructDecl.Small = @bitCast(extended.small);3526 const small: Inst.StructDecl.Small = @bitCast(extended.small);
3504 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len);3527 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).Struct.fields.len);
3528 const captures_len = if (small.has_captures_len) captures_len: {
3529 const captures_len = zir.extra[extra_index];
3530 extra_index += 1;
3531 break :captures_len captures_len;
3532 } else 0;
3505 extra_index += @intFromBool(small.has_fields_len);3533 extra_index += @intFromBool(small.has_fields_len);
3506 const decls_len = if (small.has_decls_len) decls_len: {3534 const decls_len = if (small.has_decls_len) decls_len: {
3507 const decls_len = zir.extra[extra_index];3535 const decls_len = zir.extra[extra_index];
...@@ -3509,6 +3537,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3509,6 +3537,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3509 break :decls_len decls_len;3537 break :decls_len decls_len;
3510 } else 0;3538 } else 0;
35113539
3540 extra_index += captures_len;
3541
3512 if (small.has_backing_int) {3542 if (small.has_backing_int) {
3513 const backing_int_body_len = zir.extra[extra_index];3543 const backing_int_body_len = zir.extra[extra_index];
3514 extra_index += 1; // backing_int_body_len3544 extra_index += 1; // backing_int_body_len
...@@ -3529,6 +3559,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3529,6 +3559,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3529 const small: Inst.EnumDecl.Small = @bitCast(extended.small);3559 const small: Inst.EnumDecl.Small = @bitCast(extended.small);
3530 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len);3560 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).Struct.fields.len);
3531 extra_index += @intFromBool(small.has_tag_type);3561 extra_index += @intFromBool(small.has_tag_type);
3562 const captures_len = if (small.has_captures_len) captures_len: {
3563 const captures_len = zir.extra[extra_index];
3564 extra_index += 1;
3565 break :captures_len captures_len;
3566 } else 0;
3532 extra_index += @intFromBool(small.has_body_len);3567 extra_index += @intFromBool(small.has_body_len);
3533 extra_index += @intFromBool(small.has_fields_len);3568 extra_index += @intFromBool(small.has_fields_len);
3534 const decls_len = if (small.has_decls_len) decls_len: {3569 const decls_len = if (small.has_decls_len) decls_len: {
...@@ -3537,6 +3572,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3537,6 +3572,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3537 break :decls_len decls_len;3572 break :decls_len decls_len;
3538 } else 0;3573 } else 0;
35393574
3575 extra_index += captures_len;
3576
3540 return .{3577 return .{
3541 .extra_index = extra_index,3578 .extra_index = extra_index,
3542 .decls_remaining = decls_len,3579 .decls_remaining = decls_len,
...@@ -3547,6 +3584,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3547,6 +3584,11 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3547 const small: Inst.UnionDecl.Small = @bitCast(extended.small);3584 const small: Inst.UnionDecl.Small = @bitCast(extended.small);
3548 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len);3585 var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).Struct.fields.len);
3549 extra_index += @intFromBool(small.has_tag_type);3586 extra_index += @intFromBool(small.has_tag_type);
3587 const captures_len = if (small.has_captures_len) captures_len: {
3588 const captures_len = zir.extra[extra_index];
3589 extra_index += 1;
3590 break :captures_len captures_len;
3591 } else 0;
3550 extra_index += @intFromBool(small.has_body_len);3592 extra_index += @intFromBool(small.has_body_len);
3551 extra_index += @intFromBool(small.has_fields_len);3593 extra_index += @intFromBool(small.has_fields_len);
3552 const decls_len = if (small.has_decls_len) decls_len: {3594 const decls_len = if (small.has_decls_len) decls_len: {
...@@ -3555,6 +3597,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3555,6 +3597,8 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3555 break :decls_len decls_len;3597 break :decls_len decls_len;
3556 } else 0;3598 } else 0;
35573599
3600 extra_index += captures_len;
3601
3558 return .{3602 return .{
3559 .extra_index = extra_index,3603 .extra_index = extra_index,
3560 .decls_remaining = decls_len,3604 .decls_remaining = decls_len,
...@@ -3569,6 +3613,13 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {...@@ -3569,6 +3613,13 @@ pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
3569 extra_index += 1;3613 extra_index += 1;
3570 break :decls_len decls_len;3614 break :decls_len decls_len;
3571 } else 0;3615 } else 0;
3616 const captures_len = if (small.has_captures_len) captures_len: {
3617 const captures_len = zir.extra[extra_index];
3618 extra_index += 1;
3619 break :captures_len captures_len;
3620 } else 0;
3621
3622 extra_index += captures_len;
35723623
3573 return .{3624 return .{
3574 .extra_index = extra_index,3625 .extra_index = extra_index,
src/Autodoc.zig+56-24
...@@ -450,7 +450,7 @@ const Scope = struct {...@@ -450,7 +450,7 @@ const Scope = struct {
450 Zir.NullTerminatedString, // index into the current file's string table (decl name)450 Zir.NullTerminatedString, // index into the current file's string table (decl name)
451 *DeclStatus,451 *DeclStatus,
452 ) = .{},452 ) = .{},
453453 captures: []const Zir.Inst.Capture = &.{},
454 enclosing_type: ?usize, // index into `types`, null = file top-level struct454 enclosing_type: ?usize, // index into `types`, null = file top-level struct
455455
456 pub const DeclStatus = union(enum) {456 pub const DeclStatus = union(enum) {
...@@ -459,6 +459,14 @@ const Scope = struct {...@@ -459,6 +459,14 @@ const Scope = struct {
459 NotRequested: u32, // instr_index459 NotRequested: u32, // instr_index
460 };460 };
461461
462 fn getCapture(scope: Scope, idx: u16) struct { Zir.Inst.Index, *Scope } {
463 const parent = scope.parent.?;
464 return switch (scope.captures[idx].unwrap()) {
465 .inst => |inst| .{ inst, parent },
466 .nested => |parent_idx| parent.getCapture(parent_idx),
467 };
468 }
469
462 /// Returns a pointer so that the caller has a chance to modify the value470 /// Returns a pointer so that the caller has a chance to modify the value
463 /// in case they decide to start analyzing a previously not requested decl.471 /// in case they decide to start analyzing a previously not requested decl.
464 /// Another reason is that in some places we use the pointer to uniquely472 /// Another reason is that in some places we use the pointer to uniquely
...@@ -1151,29 +1159,6 @@ fn walkInstruction(...@@ -1151,29 +1159,6 @@ fn walkInstruction(
1151 .expr = .{ .comptimeExpr = 0 },1159 .expr = .{ .comptimeExpr = 0 },
1152 };1160 };
1153 },1161 },
1154 .closure_get => {
1155 const inst_node = data[@intFromEnum(inst)].inst_node;
1156
1157 const code = try self.getBlockSource(file, parent_src, inst_node.src_node);
1158 const idx = self.comptime_exprs.items.len;
1159 try self.exprs.append(self.arena, .{ .comptimeExpr = idx });
1160 try self.comptime_exprs.append(self.arena, .{ .code = code });
1161
1162 return DocData.WalkResult{
1163 .expr = .{ .comptimeExpr = idx },
1164 };
1165 },
1166 .closure_capture => {
1167 const un_tok = data[@intFromEnum(inst)].un_tok;
1168 return try self.walkRef(
1169 file,
1170 parent_scope,
1171 parent_src,
1172 un_tok.operand,
1173 need_type,
1174 call_ctx,
1175 );
1176 },
1177 .str => {1162 .str => {
1178 const str = data[@intFromEnum(inst)].str.get(file.zir);1163 const str = data[@intFromEnum(inst)].str.get(file.zir);
11791164
...@@ -3395,11 +3380,23 @@ fn walkInstruction(...@@ -3395,11 +3380,23 @@ fn walkInstruction(
3395 .enclosing_type = type_slot_index,3380 .enclosing_type = type_slot_index,
3396 };3381 };
33973382
3383 const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small);
3398 const extra = file.zir.extraData(Zir.Inst.OpaqueDecl, extended.operand);3384 const extra = file.zir.extraData(Zir.Inst.OpaqueDecl, extended.operand);
3399 var extra_index: usize = extra.end;3385 var extra_index: usize = extra.end;
34003386
3401 const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src);3387 const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src);
34023388
3389 const captures_len = if (small.has_captures_len) blk: {
3390 const captures_len = file.zir.extra[extra_index];
3391 extra_index += 1;
3392 break :blk captures_len;
3393 } else 0;
3394
3395 if (small.has_decls_len) extra_index += 1;
3396
3397 scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]);
3398 extra_index += captures_len;
3399
3403 var decl_indexes: std.ArrayListUnmanaged(usize) = .{};3400 var decl_indexes: std.ArrayListUnmanaged(usize) = .{};
3404 var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{};3401 var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{};
34053402
...@@ -3503,6 +3500,12 @@ fn walkInstruction(...@@ -3503,6 +3500,12 @@ fn walkInstruction(
3503 break :blk tag_ref;3500 break :blk tag_ref;
3504 } else null;3501 } else null;
35053502
3503 const captures_len = if (small.has_captures_len) blk: {
3504 const captures_len = file.zir.extra[extra_index];
3505 extra_index += 1;
3506 break :blk captures_len;
3507 } else 0;
3508
3506 const body_len = if (small.has_body_len) blk: {3509 const body_len = if (small.has_body_len) blk: {
3507 const body_len = file.zir.extra[extra_index];3510 const body_len = file.zir.extra[extra_index];
3508 extra_index += 1;3511 extra_index += 1;
...@@ -3520,6 +3523,11 @@ fn walkInstruction(...@@ -3520,6 +3523,11 @@ fn walkInstruction(
3520 else => .{ .enumLiteral = @tagName(small.layout) },3523 else => .{ .enumLiteral = @tagName(small.layout) },
3521 };3524 };
35223525
3526 if (small.has_decls_len) extra_index += 1;
3527
3528 scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]);
3529 extra_index += captures_len;
3530
3523 var decl_indexes: std.ArrayListUnmanaged(usize) = .{};3531 var decl_indexes: std.ArrayListUnmanaged(usize) = .{};
3524 var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{};3532 var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{};
35253533
...@@ -3631,6 +3639,12 @@ fn walkInstruction(...@@ -3631,6 +3639,12 @@ fn walkInstruction(
3631 break :blk wr.expr;3639 break :blk wr.expr;
3632 } else null;3640 } else null;
36333641
3642 const captures_len = if (small.has_captures_len) blk: {
3643 const captures_len = file.zir.extra[extra_index];
3644 extra_index += 1;
3645 break :blk captures_len;
3646 } else 0;
3647
3634 const body_len = if (small.has_body_len) blk: {3648 const body_len = if (small.has_body_len) blk: {
3635 const body_len = file.zir.extra[extra_index];3649 const body_len = file.zir.extra[extra_index];
3636 extra_index += 1;3650 extra_index += 1;
...@@ -3643,6 +3657,11 @@ fn walkInstruction(...@@ -3643,6 +3657,11 @@ fn walkInstruction(
3643 break :blk fields_len;3657 break :blk fields_len;
3644 } else 0;3658 } else 0;
36453659
3660 if (small.has_decls_len) extra_index += 1;
3661
3662 scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]);
3663 extra_index += captures_len;
3664
3646 var decl_indexes: std.ArrayListUnmanaged(usize) = .{};3665 var decl_indexes: std.ArrayListUnmanaged(usize) = .{};
3647 var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{};3666 var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{};
36483667
...@@ -3759,6 +3778,12 @@ fn walkInstruction(...@@ -3759,6 +3778,12 @@ fn walkInstruction(
37593778
3760 const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src);3779 const src_info = try self.srcLocInfo(file, extra.data.src_node, parent_src);
37613780
3781 const captures_len = if (small.has_captures_len) blk: {
3782 const captures_len = file.zir.extra[extra_index];
3783 extra_index += 1;
3784 break :blk captures_len;
3785 } else 0;
3786
3762 const fields_len = if (small.has_fields_len) blk: {3787 const fields_len = if (small.has_fields_len) blk: {
3763 const fields_len = file.zir.extra[extra_index];3788 const fields_len = file.zir.extra[extra_index];
3764 extra_index += 1;3789 extra_index += 1;
...@@ -3768,6 +3793,9 @@ fn walkInstruction(...@@ -3768,6 +3793,9 @@ fn walkInstruction(
3768 // We don't care about decls yet3793 // We don't care about decls yet
3769 if (small.has_decls_len) extra_index += 1;3794 if (small.has_decls_len) extra_index += 1;
37703795
3796 scope.captures = @ptrCast(file.zir.extra[extra_index..][0..captures_len]);
3797 extra_index += captures_len;
3798
3771 var backing_int: ?DocData.Expr = null;3799 var backing_int: ?DocData.Expr = null;
3772 if (small.has_backing_int) {3800 if (small.has_backing_int) {
3773 const backing_int_body_len = file.zir.extra[extra_index];3801 const backing_int_body_len = file.zir.extra[extra_index];
...@@ -4018,6 +4046,10 @@ fn walkInstruction(...@@ -4018,6 +4046,10 @@ fn walkInstruction(
4018 .expr = .{ .cmpxchgIndex = cmpxchg_index },4046 .expr = .{ .cmpxchgIndex = cmpxchg_index },
4019 };4047 };
4020 },4048 },
4049 .closure_get => {
4050 const captured, const scope = parent_scope.getCapture(extended.small);
4051 return self.walkInstruction(file, scope, parent_src, captured, need_type, call_ctx);
4052 },
4021 }4053 }
4022 },4054 },
4023 }4055 }
src/InternPool.zig+1-2
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1//! All interned objects have both a value and a type.1//! All interned objects have both a value and a type.
2//! This data structure is self-contained, with the following exceptions:2//! This data structure is self-contained, with the following exceptions:
3//! * Module.Namespace has a pointer to Module.File3//! * Module.Namespace has a pointer to Module.File
4//! * Module.Decl has a pointer to Module.CaptureScope
54
6/// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are5/// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are
7/// constructed lazily.6/// constructed lazily.
...@@ -6395,7 +6394,6 @@ fn finishFuncInstance(...@@ -6395,7 +6394,6 @@ fn finishFuncInstance(
6395 .@"addrspace" = fn_owner_decl.@"addrspace",6394 .@"addrspace" = fn_owner_decl.@"addrspace",
6396 .analysis = .complete,6395 .analysis = .complete,
6397 .zir_decl_index = fn_owner_decl.zir_decl_index,6396 .zir_decl_index = fn_owner_decl.zir_decl_index,
6398 .src_scope = fn_owner_decl.src_scope,
6399 .is_pub = fn_owner_decl.is_pub,6397 .is_pub = fn_owner_decl.is_pub,
6400 .is_exported = fn_owner_decl.is_exported,6398 .is_exported = fn_owner_decl.is_exported,
6401 .alive = true,6399 .alive = true,
...@@ -7891,6 +7889,7 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex)...@@ -7891,6 +7889,7 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex)
7891 .parent = undefined,7889 .parent = undefined,
7892 .file_scope = undefined,7890 .file_scope = undefined,
7893 .decl_index = undefined,7891 .decl_index = undefined,
7892 .captures = undefined,
7894 };7893 };
7895 ip.namespaces_free_list.append(gpa, index) catch {7894 ip.namespaces_free_list.append(gpa, index) catch {
7896 // In order to keep `destroyNamespace` a non-fallible function, we ignore memory7895 // In order to keep `destroyNamespace` a non-fallible function, we ignore memory
src/Module.zig+48-52
...@@ -101,17 +101,6 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{},...@@ -101,17 +101,6 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{},
101/// is not yet implemented.101/// is not yet implemented.
102intern_pool: InternPool = .{},102intern_pool: InternPool = .{},
103103
104/// The index type for this array is `CaptureScope.Index` and the elements here are
105/// the indexes of the parent capture scopes.
106/// Memory is owned by gpa; garbage collected.
107capture_scope_parents: std.ArrayListUnmanaged(CaptureScope.Index) = .{},
108/// Value is index of type
109/// Memory is owned by gpa; garbage collected.
110runtime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternPool.Index) = .{},
111/// Value is index of value
112/// Memory is owned by gpa; garbage collected.
113comptime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternPool.Index) = .{},
114
115/// To be eliminated in a future commit by moving more data into InternPool.104/// To be eliminated in a future commit by moving more data into InternPool.
116/// Current uses that must be eliminated:105/// Current uses that must be eliminated:
117/// * comptime pointer mutation106/// * comptime pointer mutation
...@@ -305,28 +294,6 @@ pub const Export = struct {...@@ -305,28 +294,6 @@ pub const Export = struct {
305 }294 }
306};295};
307296
308pub const CaptureScope = struct {
309 pub const Key = extern struct {
310 zir_index: Zir.Inst.Index,
311 index: Index,
312 };
313
314 /// Index into `capture_scope_parents` which uniquely identifies a capture scope.
315 pub const Index = enum(u32) {
316 none = std.math.maxInt(u32),
317 _,
318
319 pub fn parent(i: Index, mod: *Module) Index {
320 return mod.capture_scope_parents.items[@intFromEnum(i)];
321 }
322 };
323};
324
325pub fn createCaptureScope(mod: *Module, parent: CaptureScope.Index) error{OutOfMemory}!CaptureScope.Index {
326 try mod.capture_scope_parents.append(mod.gpa, parent);
327 return @enumFromInt(mod.capture_scope_parents.items.len - 1);
328}
329
330const ValueArena = struct {297const ValueArena = struct {
331 state: std.heap.ArenaAllocator.State,298 state: std.heap.ArenaAllocator.State,
332 state_acquired: ?*std.heap.ArenaAllocator.State = null,299 state_acquired: ?*std.heap.ArenaAllocator.State = null,
...@@ -386,9 +353,6 @@ pub const Decl = struct {...@@ -386,9 +353,6 @@ pub const Decl = struct {
386 /// there is no parent.353 /// there is no parent.
387 src_namespace: Namespace.Index,354 src_namespace: Namespace.Index,
388355
389 /// The scope which lexically contains this decl.
390 src_scope: CaptureScope.Index,
391
392 /// The AST node index of this declaration.356 /// The AST node index of this declaration.
393 /// Must be recomputed when the corresponding source file is modified.357 /// Must be recomputed when the corresponding source file is modified.
394 src_node: Ast.Node.Index,358 src_node: Ast.Node.Index,
...@@ -792,11 +756,41 @@ pub const Namespace = struct {...@@ -792,11 +756,41 @@ pub const Namespace = struct {
792 /// These are only declarations named directly by the AST; anonymous756 /// These are only declarations named directly by the AST; anonymous
793 /// declarations are not stored here.757 /// declarations are not stored here.
794 decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},758 decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},
795
796 /// Key is usingnamespace Decl itself. To find the namespace being included,759 /// Key is usingnamespace Decl itself. To find the namespace being included,
797 /// the Decl Value has to be resolved as a Type which has a Namespace.760 /// the Decl Value has to be resolved as a Type which has a Namespace.
798 /// Value is whether the usingnamespace decl is marked `pub`.761 /// Value is whether the usingnamespace decl is marked `pub`.
799 usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{},762 usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{},
763 /// Allocated into `gpa`.
764 /// The ordered set of values captured in this type's closure.
765 /// `closure_get` instructions look up values in this list.
766 captures: []CaptureValue,
767
768 /// A single value captured in a container's closure. This is not an
769 /// `InternPool.Index` so we can differentiate between runtime-known values
770 /// (where only the type is comptime-known) and comptime-known values.
771 pub const CaptureValue = enum(u32) {
772 _,
773 pub const Unwrapped = union(enum) {
774 /// Index refers to the value.
775 @"comptime": InternPool.Index,
776 /// Index refers to the type.
777 runtime: InternPool.Index,
778 };
779 pub fn wrap(val: Unwrapped) CaptureValue {
780 return switch (val) {
781 .@"comptime" => |i| @enumFromInt(@intFromEnum(i)),
782 .runtime => |i| @enumFromInt((1 << 31) | @intFromEnum(i)),
783 };
784 }
785 pub fn unwrap(val: CaptureValue) Unwrapped {
786 const tag: u1 = @intCast(@intFromEnum(val) >> 31);
787 const raw = @intFromEnum(val);
788 return switch (tag) {
789 0 => .{ .@"comptime" = @enumFromInt(raw) },
790 1 => .{ .runtime = @enumFromInt(@as(u31, @truncate(raw))) },
791 };
792 }
793 };
800794
801 const Index = InternPool.NamespaceIndex;795 const Index = InternPool.NamespaceIndex;
802 const OptionalIndex = InternPool.OptionalNamespaceIndex;796 const OptionalIndex = InternPool.OptionalNamespaceIndex;
...@@ -2135,15 +2129,12 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2135,15 +2129,12 @@ pub fn deinit(zcu: *Zcu) void {
2135 while (it.next()) |namespace| {2129 while (it.next()) |namespace| {
2136 namespace.decls.deinit(gpa);2130 namespace.decls.deinit(gpa);
2137 namespace.usingnamespace_set.deinit(gpa);2131 namespace.usingnamespace_set.deinit(gpa);
2132 gpa.free(namespace.captures);
2138 }2133 }
2139 }2134 }
21402135
2141 zcu.intern_pool.deinit(gpa);2136 zcu.intern_pool.deinit(gpa);
2142 zcu.tmp_hack_arena.deinit();2137 zcu.tmp_hack_arena.deinit();
2143
2144 zcu.capture_scope_parents.deinit(gpa);
2145 zcu.runtime_capture_scopes.deinit(gpa);
2146 zcu.comptime_capture_scopes.deinit(gpa);
2147}2138}
21482139
2149pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {2140pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
...@@ -3362,11 +3353,12 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3362,11 +3353,12 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
3362 .parent = .none,3353 .parent = .none,
3363 .decl_index = undefined,3354 .decl_index = undefined,
3364 .file_scope = file,3355 .file_scope = file,
3356 .captures = &.{},
3365 });3357 });
3366 const new_namespace = mod.namespacePtr(new_namespace_index);3358 const new_namespace = mod.namespacePtr(new_namespace_index);
3367 errdefer mod.destroyNamespace(new_namespace_index);3359 errdefer mod.destroyNamespace(new_namespace_index);
33683360
3369 const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0, .none);3361 const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0);
3370 const new_decl = mod.declPtr(new_decl_index);3362 const new_decl = mod.declPtr(new_decl_index);
3371 errdefer @panic("TODO error handling");3363 errdefer @panic("TODO error handling");
33723364
...@@ -3420,9 +3412,18 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3420,9 +3412,18 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
3420 const struct_ty = sema.getStructType(3412 const struct_ty = sema.getStructType(
3421 new_decl_index,3413 new_decl_index,
3422 new_namespace_index,3414 new_namespace_index,
3415 null,
3423 try mod.intern_pool.trackZir(gpa, file, .main_struct_inst),3416 try mod.intern_pool.trackZir(gpa, file, .main_struct_inst),
3424 ) catch |err| switch (err) {3417 ) catch |err| switch (err) {
3425 error.OutOfMemory => return error.OutOfMemory,3418 error.OutOfMemory => return error.OutOfMemory,
3419 // The following errors are from resolving capture values, but the root
3420 // struct of a file has no captures.
3421 error.AnalysisFail,
3422 error.NeededSourceLocation,
3423 error.GenericPoison,
3424 error.ComptimeReturn,
3425 error.ComptimeBreak,
3426 => unreachable,
3426 };3427 };
3427 // TODO: figure out InternPool removals for incremental compilation3428 // TODO: figure out InternPool removals for incremental compilation
3428 //errdefer ip.remove(struct_ty);3429 //errdefer ip.remove(struct_ty);
...@@ -3573,7 +3574,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3573,7 +3574,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3573 .sema = &sema,3574 .sema = &sema,
3574 .src_decl = decl_index,3575 .src_decl = decl_index,
3575 .namespace = decl.src_namespace,3576 .namespace = decl.src_namespace,
3576 .wip_capture_scope = try mod.createCaptureScope(decl.src_scope),
3577 .instructions = .{},3577 .instructions = .{},
3578 .inlining = null,3578 .inlining = null,
3579 .is_comptime = true,3579 .is_comptime = true,
...@@ -4205,7 +4205,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void...@@ -4205,7 +4205,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void
4205 );4205 );
4206 const comp = zcu.comp;4206 const comp = zcu.comp;
4207 if (!gop.found_existing) {4207 if (!gop.found_existing) {
4208 const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope);4208 const new_decl_index = try zcu.allocateNewDecl(namespace_index, decl_node);
4209 const new_decl = zcu.declPtr(new_decl_index);4209 const new_decl = zcu.declPtr(new_decl_index);
4210 new_decl.kind = kind;4210 new_decl.kind = kind;
4211 new_decl.name = decl_name;4211 new_decl.name = decl_name;
...@@ -4438,7 +4438,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -4438,7 +4438,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
4438 .sema = &sema,4438 .sema = &sema,
4439 .src_decl = decl_index,4439 .src_decl = decl_index,
4440 .namespace = decl.src_namespace,4440 .namespace = decl.src_namespace,
4441 .wip_capture_scope = try mod.createCaptureScope(decl.src_scope),
4442 .instructions = .{},4441 .instructions = .{},
4443 .inlining = null,4442 .inlining = null,
4444 .is_comptime = false,4443 .is_comptime = false,
...@@ -4639,7 +4638,6 @@ pub fn allocateNewDecl(...@@ -4639,7 +4638,6 @@ pub fn allocateNewDecl(
4639 mod: *Module,4638 mod: *Module,
4640 namespace: Namespace.Index,4639 namespace: Namespace.Index,
4641 src_node: Ast.Node.Index,4640 src_node: Ast.Node.Index,
4642 src_scope: CaptureScope.Index,
4643) !Decl.Index {4641) !Decl.Index {
4644 const ip = &mod.intern_pool;4642 const ip = &mod.intern_pool;
4645 const gpa = mod.gpa;4643 const gpa = mod.gpa;
...@@ -4657,7 +4655,6 @@ pub fn allocateNewDecl(...@@ -4657,7 +4655,6 @@ pub fn allocateNewDecl(
4657 .@"addrspace" = .generic,4655 .@"addrspace" = .generic,
4658 .analysis = .unreferenced,4656 .analysis = .unreferenced,
4659 .zir_decl_index = .none,4657 .zir_decl_index = .none,
4660 .src_scope = src_scope,
4661 .is_pub = false,4658 .is_pub = false,
4662 .is_exported = false,4659 .is_exported = false,
4663 .alive = false,4660 .alive = false,
...@@ -4697,17 +4694,16 @@ pub fn errorSetBits(mod: *Module) u16 {...@@ -4697,17 +4694,16 @@ pub fn errorSetBits(mod: *Module) u16 {
46974694
4698pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {4695pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
4699 const src_decl = mod.declPtr(block.src_decl);4696 const src_decl = mod.declPtr(block.src_decl);
4700 return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value);4697 return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, typed_value);
4701}4698}
47024699
4703pub fn createAnonymousDeclFromDecl(4700pub fn createAnonymousDeclFromDecl(
4704 mod: *Module,4701 mod: *Module,
4705 src_decl: *Decl,4702 src_decl: *Decl,
4706 namespace: Namespace.Index,4703 namespace: Namespace.Index,
4707 src_scope: CaptureScope.Index,
4708 tv: TypedValue,4704 tv: TypedValue,
4709) !Decl.Index {4705) !Decl.Index {
4710 const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope);4706 const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node);
4711 errdefer mod.destroyDecl(new_decl_index);4707 errdefer mod.destroyDecl(new_decl_index);
4712 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{4708 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{
4713 src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),4709 src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),
...@@ -5276,7 +5272,7 @@ pub fn populateTestFunctions(...@@ -5276,7 +5272,7 @@ pub fn populateTestFunctions(
5276 .len = test_decl_name.len,5272 .len = test_decl_name.len,
5277 .child = .u8_type,5273 .child = .u8_type,
5278 });5274 });
5279 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .none, .{5275 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{
5280 .ty = test_name_decl_ty,5276 .ty = test_name_decl_ty,
5281 .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{5277 .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{
5282 .ty = test_name_decl_ty.toIntern(),5278 .ty = test_name_decl_ty.toIntern(),
...@@ -5322,7 +5318,7 @@ pub fn populateTestFunctions(...@@ -5322,7 +5318,7 @@ pub fn populateTestFunctions(
5322 .child = test_fn_ty.toIntern(),5318 .child = test_fn_ty.toIntern(),
5323 .sentinel = .none,5319 .sentinel = .none,
5324 });5320 });
5325 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .none, .{5321 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{
5326 .ty = array_decl_ty,5322 .ty = array_decl_ty,
5327 .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{5323 .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{
5328 .ty = array_decl_ty.toIntern(),5324 .ty = array_decl_ty.toIntern(),
src/Sema.zig+114-117
...@@ -155,7 +155,6 @@ const Namespace = Module.Namespace;...@@ -155,7 +155,6 @@ const Namespace = Module.Namespace;
155const CompileError = Module.CompileError;155const CompileError = Module.CompileError;
156const SemaError = Module.SemaError;156const SemaError = Module.SemaError;
157const Decl = Module.Decl;157const Decl = Module.Decl;
158const CaptureScope = Module.CaptureScope;
159const LazySrcLoc = std.zig.LazySrcLoc;158const LazySrcLoc = std.zig.LazySrcLoc;
160const RangeSet = @import("RangeSet.zig");159const RangeSet = @import("RangeSet.zig");
161const target_util = @import("target.zig");160const target_util = @import("target.zig");
...@@ -331,8 +330,6 @@ pub const Block = struct {...@@ -331,8 +330,6 @@ pub const Block = struct {
331 /// used to add a `func_instance` into the `InternPool`.330 /// used to add a `func_instance` into the `InternPool`.
332 params: std.MultiArrayList(Param) = .{},331 params: std.MultiArrayList(Param) = .{},
333332
334 wip_capture_scope: CaptureScope.Index,
335
336 label: ?*Label = null,333 label: ?*Label = null,
337 inlining: ?*Inlining,334 inlining: ?*Inlining,
338 /// If runtime_index is not 0 then one of these is guaranteed to be non null.335 /// If runtime_index is not 0 then one of these is guaranteed to be non null.
...@@ -475,7 +472,6 @@ pub const Block = struct {...@@ -475,7 +472,6 @@ pub const Block = struct {
475 .src_decl = parent.src_decl,472 .src_decl = parent.src_decl,
476 .namespace = parent.namespace,473 .namespace = parent.namespace,
477 .instructions = .{},474 .instructions = .{},
478 .wip_capture_scope = parent.wip_capture_scope,
479 .label = null,475 .label = null,
480 .inlining = parent.inlining,476 .inlining = parent.inlining,
481 .is_comptime = parent.is_comptime,477 .is_comptime = parent.is_comptime,
...@@ -974,12 +970,6 @@ fn analyzeBodyInner(...@@ -974,12 +970,6 @@ fn analyzeBodyInner(
974970
975 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body);971 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body);
976972
977 // Most of the time, we don't need to construct a new capture scope for a
978 // block. However, successive iterations of comptime loops can capture
979 // different values for the same Zir.Inst.Index, so in those cases, we will
980 // have to create nested capture scopes; see the `.repeat` case below.
981 const parent_capture_scope = block.wip_capture_scope;
982
983 const mod = sema.mod;973 const mod = sema.mod;
984 const map = &sema.inst_map;974 const map = &sema.inst_map;
985 const tags = sema.code.instructions.items(.tag);975 const tags = sema.code.instructions.items(.tag);
...@@ -1028,7 +1018,6 @@ fn analyzeBodyInner(...@@ -1028,7 +1018,6 @@ fn analyzeBodyInner(
1028 .c_import => try sema.zirCImport(block, inst),1018 .c_import => try sema.zirCImport(block, inst),
1029 .call => try sema.zirCall(block, inst, .direct),1019 .call => try sema.zirCall(block, inst, .direct),
1030 .field_call => try sema.zirCall(block, inst, .field),1020 .field_call => try sema.zirCall(block, inst, .field),
1031 .closure_get => try sema.zirClosureGet(block, inst),
1032 .cmp_lt => try sema.zirCmp(block, inst, .lt),1021 .cmp_lt => try sema.zirCmp(block, inst, .lt),
1033 .cmp_lte => try sema.zirCmp(block, inst, .lte),1022 .cmp_lte => try sema.zirCmp(block, inst, .lte),
1034 .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)),1023 .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .Optimized)),
...@@ -1275,6 +1264,7 @@ fn analyzeBodyInner(...@@ -1275,6 +1264,7 @@ fn analyzeBodyInner(
1275 .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode),1264 .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode),
1276 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),1265 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),
1277 .in_comptime => try sema.zirInComptime( block),1266 .in_comptime => try sema.zirInComptime( block),
1267 .closure_get => try sema.zirClosureGet( block, extended),
1278 // zig fmt: on1268 // zig fmt: on
12791269
1280 .fence => {1270 .fence => {
...@@ -1453,11 +1443,6 @@ fn analyzeBodyInner(...@@ -1453,11 +1443,6 @@ fn analyzeBodyInner(
1453 i += 1;1443 i += 1;
1454 continue;1444 continue;
1455 },1445 },
1456 .closure_capture => {
1457 try sema.zirClosureCapture(block, inst);
1458 i += 1;
1459 continue;
1460 },
1461 .memcpy => {1446 .memcpy => {
1462 try sema.zirMemcpy(block, inst);1447 try sema.zirMemcpy(block, inst);
1463 i += 1;1448 i += 1;
...@@ -1534,11 +1519,6 @@ fn analyzeBodyInner(...@@ -1534,11 +1519,6 @@ fn analyzeBodyInner(
1534 // Send comptime control flow back to the beginning of this block.1519 // Send comptime control flow back to the beginning of this block.
1535 const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node);1520 const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node);
1536 try sema.emitBackwardBranch(block, src);1521 try sema.emitBackwardBranch(block, src);
1537
1538 // We need to construct new capture scopes for the next loop iteration so it
1539 // can capture values without clobbering the earlier iteration's captures.
1540 block.wip_capture_scope = try mod.createCaptureScope(parent_capture_scope);
1541
1542 i = 0;1522 i = 0;
1543 continue;1523 continue;
1544 } else {1524 } else {
...@@ -1552,11 +1532,6 @@ fn analyzeBodyInner(...@@ -1552,11 +1532,6 @@ fn analyzeBodyInner(
1552 // Send comptime control flow back to the beginning of this block.1532 // Send comptime control flow back to the beginning of this block.
1553 const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node);1533 const src = LazySrcLoc.nodeOffset(datas[@intFromEnum(inst)].node);
1554 try sema.emitBackwardBranch(block, src);1534 try sema.emitBackwardBranch(block, src);
1555
1556 // We need to construct new capture scopes for the next loop iteration so it
1557 // can capture values without clobbering the earlier iteration's captures.
1558 block.wip_capture_scope = try mod.createCaptureScope(parent_capture_scope);
1559
1560 i = 0;1535 i = 0;
1561 continue;1536 continue;
1562 },1537 },
...@@ -1855,10 +1830,6 @@ fn analyzeBodyInner(...@@ -1855,10 +1830,6 @@ fn analyzeBodyInner(
1855 map.putAssumeCapacity(inst, air_inst);1830 map.putAssumeCapacity(inst, air_inst);
1856 i += 1;1831 i += 1;
1857 }1832 }
1858
1859 // We may have overwritten the capture scope due to a `repeat` instruction where
1860 // the body had a capture; restore it now.
1861 block.wip_capture_scope = parent_capture_scope;
1862}1833}
18631834
1864pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {1835pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
...@@ -2698,10 +2669,41 @@ fn analyzeAsInt(...@@ -2698,10 +2669,41 @@ fn analyzeAsInt(
2698 return (try val.getUnsignedIntAdvanced(mod, sema)).?;2669 return (try val.getUnsignedIntAdvanced(mod, sema)).?;
2699}2670}
27002671
2672/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
2673/// resolves this into a list of `Namespace.CaptureValue` allocated by `gpa`.
2674/// Caller owns returned memory.
2675fn getCaptures(sema: *Sema, parent_namespace: ?InternPool.NamespaceIndex, extra_index: usize, captures_len: u32) ![]Namespace.CaptureValue {
2676 const gpa = sema.gpa;
2677 const parent_captures: []const Namespace.CaptureValue = if (parent_namespace) |p| parent: {
2678 break :parent sema.mod.namespacePtr(p).captures;
2679 } else &.{};
2680
2681 const captures = try gpa.alloc(Namespace.CaptureValue, captures_len);
2682 errdefer gpa.free(captures);
2683
2684 for (sema.code.extra[extra_index..][0..captures_len], captures) |raw, *capture| {
2685 const zir_capture: Zir.Inst.Capture = @enumFromInt(raw);
2686 capture.* = switch (zir_capture.unwrap()) {
2687 .inst => |inst| Namespace.CaptureValue.wrap(capture: {
2688 const air_ref = try sema.resolveInst(inst.toRef());
2689 if (try sema.resolveValue(air_ref)) |val| {
2690 break :capture .{ .@"comptime" = val.toIntern() };
2691 }
2692 break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() };
2693 }),
2694 .nested => |parent_idx| parent_captures[parent_idx],
2695 };
2696 }
2697
2698 return captures;
2699}
2700
2701pub fn getStructType(2701pub fn getStructType(
2702 sema: *Sema,2702 sema: *Sema,
2703 decl: InternPool.DeclIndex,2703 decl: InternPool.DeclIndex,
2704 namespace: InternPool.NamespaceIndex,2704 namespace: InternPool.NamespaceIndex,
2705 /// The direct parent Namespace for resolving nested capture values.
2706 parent_namespace: ?InternPool.NamespaceIndex,
2705 tracked_inst: InternPool.TrackedInst.Index,2707 tracked_inst: InternPool.TrackedInst.Index,
2706) !InternPool.Index {2708) !InternPool.Index {
2707 const mod = sema.mod;2709 const mod = sema.mod;
...@@ -2713,6 +2715,11 @@ pub fn getStructType(...@@ -2713,6 +2715,11 @@ pub fn getStructType(
2713 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);2715 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
27142716
2715 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len;2717 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len;
2718 const captures_len = if (small.has_captures_len) blk: {
2719 const captures_len = sema.code.extra[extra_index];
2720 extra_index += 1;
2721 break :blk captures_len;
2722 } else 0;
2716 const fields_len = if (small.has_fields_len) blk: {2723 const fields_len = if (small.has_fields_len) blk: {
2717 const fields_len = sema.code.extra[extra_index];2724 const fields_len = sema.code.extra[extra_index];
2718 extra_index += 1;2725 extra_index += 1;
...@@ -2724,6 +2731,9 @@ pub fn getStructType(...@@ -2724,6 +2731,9 @@ pub fn getStructType(
2724 break :blk decls_len;2731 break :blk decls_len;
2725 } else 0;2732 } else 0;
27262733
2734 mod.namespacePtr(namespace).captures = try sema.getCaptures(parent_namespace, extra_index, captures_len);
2735 extra_index += captures_len;
2736
2727 if (small.has_backing_int) {2737 if (small.has_backing_int) {
2728 const backing_int_body_len = sema.code.extra[extra_index];2738 const backing_int_body_len = sema.code.extra[extra_index];
2729 extra_index += 1; // backing_int_body_len2739 extra_index += 1; // backing_int_body_len
...@@ -2791,12 +2801,13 @@ fn zirStructDecl(...@@ -2791,12 +2801,13 @@ fn zirStructDecl(
2791 .parent = block.namespace.toOptional(),2801 .parent = block.namespace.toOptional(),
2792 .decl_index = new_decl_index,2802 .decl_index = new_decl_index,
2793 .file_scope = block.getFileScope(mod),2803 .file_scope = block.getFileScope(mod),
2804 .captures = &.{}, // Will be set by `getStructType`
2794 });2805 });
2795 errdefer mod.destroyNamespace(new_namespace_index);2806 errdefer mod.destroyNamespace(new_namespace_index);
27962807
2797 const struct_ty = ty: {2808 const struct_ty = ty: {
2798 const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst);2809 const tracked_inst = try ip.trackZir(mod.gpa, block.getFileScope(mod), inst);
2799 const ty = try sema.getStructType(new_decl_index, new_namespace_index, tracked_inst);2810 const ty = try sema.getStructType(new_decl_index, new_namespace_index, block.namespace, tracked_inst);
2800 if (sema.builtin_type_target_index != .none) {2811 if (sema.builtin_type_target_index != .none) {
2801 ip.resolveBuiltinType(sema.builtin_type_target_index, ty);2812 ip.resolveBuiltinType(sema.builtin_type_target_index, ty);
2802 break :ty sema.builtin_type_target_index;2813 break :ty sema.builtin_type_target_index;
...@@ -2827,10 +2838,9 @@ fn createAnonymousDeclTypeNamed(...@@ -2827,10 +2838,9 @@ fn createAnonymousDeclTypeNamed(
2827 const ip = &mod.intern_pool;2838 const ip = &mod.intern_pool;
2828 const gpa = sema.gpa;2839 const gpa = sema.gpa;
2829 const namespace = block.namespace;2840 const namespace = block.namespace;
2830 const src_scope = block.wip_capture_scope;
2831 const src_decl = mod.declPtr(block.src_decl);2841 const src_decl = mod.declPtr(block.src_decl);
2832 const src_node = src_decl.relativeToNodeIndex(src.node_offset.x);2842 const src_node = src_decl.relativeToNodeIndex(src.node_offset.x);
2833 const new_decl_index = try mod.allocateNewDecl(namespace, src_node, src_scope);2843 const new_decl_index = try mod.allocateNewDecl(namespace, src_node);
2834 errdefer mod.destroyDecl(new_decl_index);2844 errdefer mod.destroyDecl(new_decl_index);
28352845
2836 switch (name_strategy) {2846 switch (name_strategy) {
...@@ -2935,6 +2945,12 @@ fn zirEnumDecl(...@@ -2935,6 +2945,12 @@ fn zirEnumDecl(
2935 break :blk tag_type_ref;2945 break :blk tag_type_ref;
2936 } else .none;2946 } else .none;
29372947
2948 const captures_len = if (small.has_captures_len) blk: {
2949 const captures_len = sema.code.extra[extra_index];
2950 extra_index += 1;
2951 break :blk captures_len;
2952 } else 0;
2953
2938 const body_len = if (small.has_body_len) blk: {2954 const body_len = if (small.has_body_len) blk: {
2939 const body_len = sema.code.extra[extra_index];2955 const body_len = sema.code.extra[extra_index];
2940 extra_index += 1;2956 extra_index += 1;
...@@ -2974,10 +2990,14 @@ fn zirEnumDecl(...@@ -2974,10 +2990,14 @@ fn zirEnumDecl(
2974 );2990 );
2975 }2991 }
29762992
2993 const captures = try sema.getCaptures(block.namespace, extra_index, captures_len);
2994 extra_index += captures_len;
2995
2977 const new_namespace_index = try mod.createNamespace(.{2996 const new_namespace_index = try mod.createNamespace(.{
2978 .parent = block.namespace.toOptional(),2997 .parent = block.namespace.toOptional(),
2979 .decl_index = new_decl_index,2998 .decl_index = new_decl_index,
2980 .file_scope = block.getFileScope(mod),2999 .file_scope = block.getFileScope(mod),
3000 .captures = captures,
2981 });3001 });
2982 errdefer if (!done) mod.destroyNamespace(new_namespace_index);3002 errdefer if (!done) mod.destroyNamespace(new_namespace_index);
29833003
...@@ -3054,7 +3074,6 @@ fn zirEnumDecl(...@@ -3054,7 +3074,6 @@ fn zirEnumDecl(
3054 .sema = sema,3074 .sema = sema,
3055 .src_decl = new_decl_index,3075 .src_decl = new_decl_index,
3056 .namespace = new_namespace_index,3076 .namespace = new_namespace_index,
3057 .wip_capture_scope = try mod.createCaptureScope(new_decl.src_scope),
3058 .instructions = .{},3077 .instructions = .{},
3059 .inlining = null,3078 .inlining = null,
3060 .is_comptime = true,3079 .is_comptime = true,
...@@ -3197,6 +3216,11 @@ fn zirUnionDecl(...@@ -3197,6 +3216,11 @@ fn zirUnionDecl(
3197 const src = extra.data.src();3216 const src = extra.data.src();
31983217
3199 extra_index += @intFromBool(small.has_tag_type);3218 extra_index += @intFromBool(small.has_tag_type);
3219 const captures_len = if (small.has_captures_len) blk: {
3220 const captures_len = sema.code.extra[extra_index];
3221 extra_index += 1;
3222 break :blk captures_len;
3223 } else 0;
3200 extra_index += @intFromBool(small.has_body_len);3224 extra_index += @intFromBool(small.has_body_len);
3201 const fields_len = if (small.has_fields_len) blk: {3225 const fields_len = if (small.has_fields_len) blk: {
3202 const fields_len = sema.code.extra[extra_index];3226 const fields_len = sema.code.extra[extra_index];
...@@ -3230,10 +3254,14 @@ fn zirUnionDecl(...@@ -3230,10 +3254,14 @@ fn zirUnionDecl(
3230 );3254 );
3231 }3255 }
32323256
3257 const captures = try sema.getCaptures(block.namespace, extra_index, captures_len);
3258 extra_index += captures_len;
3259
3233 const new_namespace_index = try mod.createNamespace(.{3260 const new_namespace_index = try mod.createNamespace(.{
3234 .parent = block.namespace.toOptional(),3261 .parent = block.namespace.toOptional(),
3235 .decl_index = new_decl_index,3262 .decl_index = new_decl_index,
3236 .file_scope = block.getFileScope(mod),3263 .file_scope = block.getFileScope(mod),
3264 .captures = captures,
3237 });3265 });
3238 errdefer mod.destroyNamespace(new_namespace_index);3266 errdefer mod.destroyNamespace(new_namespace_index);
32393267
...@@ -3300,6 +3328,12 @@ fn zirOpaqueDecl(...@@ -3300,6 +3328,12 @@ fn zirOpaqueDecl(
33003328
3301 const src = extra.data.src();3329 const src = extra.data.src();
33023330
3331 const captures_len = if (small.has_captures_len) blk: {
3332 const captures_len = sema.code.extra[extra_index];
3333 extra_index += 1;
3334 break :blk captures_len;
3335 } else 0;
3336
3303 const decls_len = if (small.has_decls_len) blk: {3337 const decls_len = if (small.has_decls_len) blk: {
3304 const decls_len = sema.code.extra[extra_index];3338 const decls_len = sema.code.extra[extra_index];
3305 extra_index += 1;3339 extra_index += 1;
...@@ -3326,10 +3360,14 @@ fn zirOpaqueDecl(...@@ -3326,10 +3360,14 @@ fn zirOpaqueDecl(
3326 );3360 );
3327 }3361 }
33283362
3363 const captures = try sema.getCaptures(block.namespace, extra_index, captures_len);
3364 extra_index += captures_len;
3365
3329 const new_namespace_index = try mod.createNamespace(.{3366 const new_namespace_index = try mod.createNamespace(.{
3330 .parent = block.namespace.toOptional(),3367 .parent = block.namespace.toOptional(),
3331 .decl_index = new_decl_index,3368 .decl_index = new_decl_index,
3332 .file_scope = block.getFileScope(mod),3369 .file_scope = block.getFileScope(mod),
3370 .captures = captures,
3333 });3371 });
3334 errdefer mod.destroyNamespace(new_namespace_index);3372 errdefer mod.destroyNamespace(new_namespace_index);
33353373
...@@ -5780,7 +5818,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -5780,7 +5818,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5780 .sema = sema,5818 .sema = sema,
5781 .src_decl = parent_block.src_decl,5819 .src_decl = parent_block.src_decl,
5782 .namespace = parent_block.namespace,5820 .namespace = parent_block.namespace,
5783 .wip_capture_scope = parent_block.wip_capture_scope,
5784 .instructions = .{},5821 .instructions = .{},
5785 .inlining = parent_block.inlining,5822 .inlining = parent_block.inlining,
5786 .is_comptime = true,5823 .is_comptime = true,
...@@ -5900,7 +5937,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt...@@ -5900,7 +5937,6 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index, force_compt
5900 .sema = sema,5937 .sema = sema,
5901 .src_decl = parent_block.src_decl,5938 .src_decl = parent_block.src_decl,
5902 .namespace = parent_block.namespace,5939 .namespace = parent_block.namespace,
5903 .wip_capture_scope = parent_block.wip_capture_scope,
5904 .instructions = .{},5940 .instructions = .{},
5905 .label = &label,5941 .label = &label,
5906 .inlining = parent_block.inlining,5942 .inlining = parent_block.inlining,
...@@ -7515,7 +7551,6 @@ fn analyzeCall(...@@ -7515,7 +7551,6 @@ fn analyzeCall(
7515 .sema = sema,7551 .sema = sema,
7516 .src_decl = module_fn.owner_decl,7552 .src_decl = module_fn.owner_decl,
7517 .namespace = fn_owner_decl.src_namespace,7553 .namespace = fn_owner_decl.src_namespace,
7518 .wip_capture_scope = try mod.createCaptureScope(fn_owner_decl.src_scope),
7519 .instructions = .{},7554 .instructions = .{},
7520 .label = null,7555 .label = null,
7521 .inlining = &inlining,7556 .inlining = &inlining,
...@@ -8036,7 +8071,6 @@ fn instantiateGenericCall(...@@ -8036,7 +8071,6 @@ fn instantiateGenericCall(
8036 .sema = &child_sema,8071 .sema = &child_sema,
8037 .src_decl = generic_owner_func.owner_decl,8072 .src_decl = generic_owner_func.owner_decl,
8038 .namespace = namespace_index,8073 .namespace = namespace_index,
8039 .wip_capture_scope = try mod.createCaptureScope(fn_owner_decl.src_scope),
8040 .instructions = .{},8074 .instructions = .{},
8041 .inlining = null,8075 .inlining = null,
8042 .is_comptime = true,8076 .is_comptime = true,
...@@ -11409,7 +11443,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11409,7 +11443,6 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11409 .sema = sema,11443 .sema = sema,
11410 .src_decl = block.src_decl,11444 .src_decl = block.src_decl,
11411 .namespace = block.namespace,11445 .namespace = block.namespace,
11412 .wip_capture_scope = block.wip_capture_scope,
11413 .instructions = .{},11446 .instructions = .{},
11414 .label = &label,11447 .label = &label,
11415 .inlining = block.inlining,11448 .inlining = block.inlining,
...@@ -12117,7 +12150,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12117,7 +12150,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12117 .sema = sema,12150 .sema = sema,
12118 .src_decl = block.src_decl,12151 .src_decl = block.src_decl,
12119 .namespace = block.namespace,12152 .namespace = block.namespace,
12120 .wip_capture_scope = block.wip_capture_scope,
12121 .instructions = .{},12153 .instructions = .{},
12122 .label = &label,12154 .label = &label,
12123 .inlining = block.inlining,12155 .inlining = block.inlining,
...@@ -12281,7 +12313,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12281,7 +12313,6 @@ fn analyzeSwitchRuntimeBlock(
12281 extra_index += info.body_len;12313 extra_index += info.body_len;
1228212314
12283 case_block.instructions.shrinkRetainingCapacity(0);12315 case_block.instructions.shrinkRetainingCapacity(0);
12284 case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope);
1228512316
12286 const item = case_vals.items[scalar_i];12317 const item = case_vals.items[scalar_i];
12287 // `item` is already guaranteed to be constant known.12318 // `item` is already guaranteed to be constant known.
...@@ -12339,7 +12370,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12339,7 +12370,6 @@ fn analyzeSwitchRuntimeBlock(
12339 case_val_idx += items_len;12370 case_val_idx += items_len;
1234012371
12341 case_block.instructions.shrinkRetainingCapacity(0);12372 case_block.instructions.shrinkRetainingCapacity(0);
12342 case_block.wip_capture_scope = child_block.wip_capture_scope;
1234312373
12344 // Generate all possible cases as scalar prongs.12374 // Generate all possible cases as scalar prongs.
12345 if (info.is_inline) {12375 if (info.is_inline) {
...@@ -12371,7 +12401,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12371,7 +12401,6 @@ fn analyzeSwitchRuntimeBlock(
12371 const item_ref = Air.internedToRef(item.toIntern());12401 const item_ref = Air.internedToRef(item.toIntern());
1237212402
12373 case_block.instructions.shrinkRetainingCapacity(0);12403 case_block.instructions.shrinkRetainingCapacity(0);
12374 case_block.wip_capture_scope = child_block.wip_capture_scope;
1237512404
12376 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {12405 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {
12377 error.NeededSourceLocation => {12406 error.NeededSourceLocation => {
...@@ -12411,7 +12440,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12411,7 +12440,6 @@ fn analyzeSwitchRuntimeBlock(
12411 cases_len += 1;12440 cases_len += 1;
1241212441
12413 case_block.instructions.shrinkRetainingCapacity(0);12442 case_block.instructions.shrinkRetainingCapacity(0);
12414 case_block.wip_capture_scope = child_block.wip_capture_scope;
1241512443
12416 const analyze_body = if (union_originally) blk: {12444 const analyze_body = if (union_originally) blk: {
12417 const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable;12445 const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable;
...@@ -12557,7 +12585,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12557,7 +12585,6 @@ fn analyzeSwitchRuntimeBlock(
12557 defer gpa.free(cond_body);12585 defer gpa.free(cond_body);
1255812586
12559 case_block.instructions.shrinkRetainingCapacity(0);12587 case_block.instructions.shrinkRetainingCapacity(0);
12560 case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope);
1256112588
12562 const body = sema.code.bodySlice(extra_index, info.body_len);12589 const body = sema.code.bodySlice(extra_index, info.body_len);
12563 extra_index += info.body_len;12590 extra_index += info.body_len;
...@@ -12618,7 +12645,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12618,7 +12645,6 @@ fn analyzeSwitchRuntimeBlock(
12618 const item_ref = Air.internedToRef(item_val.toIntern());12645 const item_ref = Air.internedToRef(item_val.toIntern());
1261912646
12620 case_block.instructions.shrinkRetainingCapacity(0);12647 case_block.instructions.shrinkRetainingCapacity(0);
12621 case_block.wip_capture_scope = child_block.wip_capture_scope;
1262212648
12623 const analyze_body = if (union_originally) blk: {12649 const analyze_body = if (union_originally) blk: {
12624 const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?;12650 const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?;
...@@ -12669,7 +12695,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12669,7 +12695,6 @@ fn analyzeSwitchRuntimeBlock(
12669 const item_ref = Air.internedToRef(item_val);12695 const item_ref = Air.internedToRef(item_val);
1267012696
12671 case_block.instructions.shrinkRetainingCapacity(0);12697 case_block.instructions.shrinkRetainingCapacity(0);
12672 case_block.wip_capture_scope = child_block.wip_capture_scope;
1267312698
12674 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);12699 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
12675 emit_bb = true;12700 emit_bb = true;
...@@ -12700,7 +12725,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12700,7 +12725,6 @@ fn analyzeSwitchRuntimeBlock(
12700 const item_ref = Air.internedToRef(cur);12725 const item_ref = Air.internedToRef(cur);
1270112726
12702 case_block.instructions.shrinkRetainingCapacity(0);12727 case_block.instructions.shrinkRetainingCapacity(0);
12703 case_block.wip_capture_scope = child_block.wip_capture_scope;
1270412728
12705 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);12729 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
12706 emit_bb = true;12730 emit_bb = true;
...@@ -12728,7 +12752,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12728,7 +12752,6 @@ fn analyzeSwitchRuntimeBlock(
12728 cases_len += 1;12752 cases_len += 1;
1272912753
12730 case_block.instructions.shrinkRetainingCapacity(0);12754 case_block.instructions.shrinkRetainingCapacity(0);
12731 case_block.wip_capture_scope = child_block.wip_capture_scope;
1273212755
12733 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);12756 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
12734 emit_bb = true;12757 emit_bb = true;
...@@ -12754,7 +12777,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12754,7 +12777,6 @@ fn analyzeSwitchRuntimeBlock(
12754 cases_len += 1;12777 cases_len += 1;
1275512778
12756 case_block.instructions.shrinkRetainingCapacity(0);12779 case_block.instructions.shrinkRetainingCapacity(0);
12757 case_block.wip_capture_scope = child_block.wip_capture_scope;
1275812780
12759 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);12781 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
12760 emit_bb = true;12782 emit_bb = true;
...@@ -12783,7 +12805,6 @@ fn analyzeSwitchRuntimeBlock(...@@ -12783,7 +12805,6 @@ fn analyzeSwitchRuntimeBlock(
12783 };12805 };
1278412806
12785 case_block.instructions.shrinkRetainingCapacity(0);12807 case_block.instructions.shrinkRetainingCapacity(0);
12786 case_block.wip_capture_scope = try mod.createCaptureScope(child_block.wip_capture_scope);
1278712808
12788 if (mod.backendSupportsFeature(.is_named_enum_value) and12809 if (mod.backendSupportsFeature(.is_named_enum_value) and
12789 special.body.len != 0 and block.wantSafety() and12810 special.body.len != 0 and block.wantSafety() and
...@@ -17264,49 +17285,16 @@ fn zirThis(...@@ -17264,49 +17285,16 @@ fn zirThis(
17264 return sema.analyzeDeclVal(block, src, this_decl_index);17285 return sema.analyzeDeclVal(block, src, this_decl_index);
17265}17286}
1726617287
17267fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {17288fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
17268 const mod = sema.mod;17289 const mod = sema.mod;
17269 const gpa = sema.gpa;17290 const captures = mod.namespacePtr(block.namespace).captures;
17270 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok;
17271 // Closures are not necessarily constant values. For example, the
17272 // code might do something like this:
17273 // fn foo(x: anytype) void { const S = struct {field: @TypeOf(x)}; }
17274 // ...in which case the closure_capture instruction has access to a runtime
17275 // value only. In such case only the type is saved into the scope.
17276 const operand = try sema.resolveInst(inst_data.operand);
17277 const ty = sema.typeOf(operand);
17278 const key: CaptureScope.Key = .{
17279 .zir_index = inst,
17280 .index = block.wip_capture_scope,
17281 };
17282 if (try sema.resolveValue(operand)) |val| {
17283 try mod.comptime_capture_scopes.put(gpa, key, try val.intern(ty, mod));
17284 } else {
17285 try mod.runtime_capture_scopes.put(gpa, key, ty.toIntern());
17286 }
17287}
1728817291
17289fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {17292 const src_node: i32 = @bitCast(extended.operand);
17290 const mod = sema.mod;17293 const src = LazySrcLoc.nodeOffset(src_node);
17291 //const ip = &mod.intern_pool;17294
17292 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].inst_node;17295 const capture_ty = switch (captures[extended.small].unwrap()) {
17293 var scope: CaptureScope.Index = mod.declPtr(block.src_decl).src_scope;17296 .@"comptime" => |index| return Air.internedToRef(index),
17294 assert(scope != .none);17297 .runtime => |index| index,
17295 // Note: The target closure must be in this scope list.
17296 // If it's not here, the zir is invalid, or the list is broken.
17297 const capture_ty = while (true) {
17298 // Note: We don't need to add a dependency here, because
17299 // decls always depend on their lexical parents.
17300 const key: CaptureScope.Key = .{
17301 .zir_index = inst_data.inst,
17302 .index = scope,
17303 };
17304 if (mod.comptime_capture_scopes.get(key)) |val|
17305 return Air.internedToRef(val);
17306 if (mod.runtime_capture_scopes.get(key)) |ty|
17307 break ty;
17308 scope = scope.parent(mod);
17309 assert(scope != .none);
17310 };17298 };
1731117299
17312 // The comptime case is handled already above. Runtime case below.17300 // The comptime case is handled already above. Runtime case below.
...@@ -17322,15 +17310,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -17322,15 +17310,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
17322 });17310 });
17323 break :name null;17311 break :name null;
17324 };17312 };
17325 const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node);17313 const node = sema.owner_decl.relativeToNodeIndex(src_node);
17326 const token = tree.nodes.items(.main_token)[node];17314 const token = tree.nodes.items(.main_token)[node];
17327 break :name tree.tokenSlice(token);17315 break :name tree.tokenSlice(token);
17328 };17316 };
1732917317
17330 const msg = if (name) |some|17318 const msg = if (name) |some|
17331 try sema.errMsg(block, inst_data.src(), "'{s}' not accessible outside function scope", .{some})17319 try sema.errMsg(block, src, "'{s}' not accessible outside function scope", .{some})
17332 else17320 else
17333 try sema.errMsg(block, inst_data.src(), "variable not accessible outside function scope", .{});17321 try sema.errMsg(block, src, "variable not accessible outside function scope", .{});
17334 errdefer msg.destroy(sema.gpa);17322 errdefer msg.destroy(sema.gpa);
1733517323
17336 // TODO add "declared here" note17324 // TODO add "declared here" note
...@@ -17350,15 +17338,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -17350,15 +17338,15 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
17350 });17338 });
17351 break :name null;17339 break :name null;
17352 };17340 };
17353 const node = sema.owner_decl.relativeToNodeIndex(inst_data.src_node);17341 const node = sema.owner_decl.relativeToNodeIndex(src_node);
17354 const token = tree.nodes.items(.main_token)[node];17342 const token = tree.nodes.items(.main_token)[node];
17355 break :name tree.tokenSlice(token);17343 break :name tree.tokenSlice(token);
17356 };17344 };
1735717345
17358 const msg = if (name) |some|17346 const msg = if (name) |some|
17359 try sema.errMsg(block, inst_data.src(), "'{s}' not accessible from inner function", .{some})17347 try sema.errMsg(block, src, "'{s}' not accessible from inner function", .{some})
17360 else17348 else
17361 try sema.errMsg(block, inst_data.src(), "variable not accessible from inner function", .{});17349 try sema.errMsg(block, src, "variable not accessible from inner function", .{});
17362 errdefer msg.destroy(sema.gpa);17350 errdefer msg.destroy(sema.gpa);
1736317351
17364 try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{});17352 try sema.errNote(block, LazySrcLoc.nodeOffset(0), msg, "crossed function definition here", .{});
...@@ -18631,7 +18619,6 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -18631,7 +18619,6 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
18631 .sema = sema,18619 .sema = sema,
18632 .src_decl = block.src_decl,18620 .src_decl = block.src_decl,
18633 .namespace = block.namespace,18621 .namespace = block.namespace,
18634 .wip_capture_scope = block.wip_capture_scope,
18635 .instructions = .{},18622 .instructions = .{},
18636 .inlining = block.inlining,18623 .inlining = block.inlining,
18637 .is_comptime = false,18624 .is_comptime = false,
...@@ -18710,7 +18697,6 @@ fn zirTypeofPeer(...@@ -18710,7 +18697,6 @@ fn zirTypeofPeer(
18710 .sema = sema,18697 .sema = sema,
18711 .src_decl = block.src_decl,18698 .src_decl = block.src_decl,
18712 .namespace = block.namespace,18699 .namespace = block.namespace,
18713 .wip_capture_scope = block.wip_capture_scope,
18714 .instructions = .{},18700 .instructions = .{},
18715 .inlining = block.inlining,18701 .inlining = block.inlining,
18716 .is_comptime = false,18702 .is_comptime = false,
...@@ -19186,7 +19172,6 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label...@@ -19186,7 +19172,6 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
19186 .sema = sema,19172 .sema = sema,
19187 .src_decl = block.src_decl,19173 .src_decl = block.src_decl,
19188 .namespace = block.namespace,19174 .namespace = block.namespace,
19189 .wip_capture_scope = block.wip_capture_scope,
19190 .instructions = .{},19175 .instructions = .{},
19191 .label = &labeled_block.label,19176 .label = &labeled_block.label,
19192 .inlining = block.inlining,19177 .inlining = block.inlining,
...@@ -21462,6 +21447,7 @@ fn zirReify(...@@ -21462,6 +21447,7 @@ fn zirReify(
21462 .parent = block.namespace.toOptional(),21447 .parent = block.namespace.toOptional(),
21463 .decl_index = new_decl_index,21448 .decl_index = new_decl_index,
21464 .file_scope = block.getFileScope(mod),21449 .file_scope = block.getFileScope(mod),
21450 .captures = &.{},
21465 });21451 });
21466 errdefer mod.destroyNamespace(new_namespace_index);21452 errdefer mod.destroyNamespace(new_namespace_index);
2146721453
...@@ -21670,6 +21656,7 @@ fn zirReify(...@@ -21670,6 +21656,7 @@ fn zirReify(
21670 .parent = block.namespace.toOptional(),21656 .parent = block.namespace.toOptional(),
21671 .decl_index = new_decl_index,21657 .decl_index = new_decl_index,
21672 .file_scope = block.getFileScope(mod),21658 .file_scope = block.getFileScope(mod),
21659 .captures = &.{},
21673 });21660 });
21674 errdefer mod.destroyNamespace(new_namespace_index);21661 errdefer mod.destroyNamespace(new_namespace_index);
2167521662
...@@ -25919,7 +25906,7 @@ fn zirBuiltinExtern(...@@ -25919,7 +25906,7 @@ fn zirBuiltinExtern(
2591925906
25920 // TODO check duplicate extern25907 // TODO check duplicate extern
2592125908
25922 const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, .none);25909 const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node);
25923 errdefer mod.destroyDecl(new_decl_index);25910 errdefer mod.destroyDecl(new_decl_index);
25924 const new_decl = mod.declPtr(new_decl_index);25911 const new_decl = mod.declPtr(new_decl_index);
25925 new_decl.name = options.name;25912 new_decl.name = options.name;
...@@ -26515,7 +26502,6 @@ fn addSafetyCheck(...@@ -26515,7 +26502,6 @@ fn addSafetyCheck(
26515 .sema = sema,26502 .sema = sema,
26516 .src_decl = parent_block.src_decl,26503 .src_decl = parent_block.src_decl,
26517 .namespace = parent_block.namespace,26504 .namespace = parent_block.namespace,
26518 .wip_capture_scope = parent_block.wip_capture_scope,
26519 .instructions = .{},26505 .instructions = .{},
26520 .inlining = parent_block.inlining,26506 .inlining = parent_block.inlining,
26521 .is_comptime = false,26507 .is_comptime = false,
...@@ -26624,7 +26610,6 @@ fn panicUnwrapError(...@@ -26624,7 +26610,6 @@ fn panicUnwrapError(
26624 .sema = sema,26610 .sema = sema,
26625 .src_decl = parent_block.src_decl,26611 .src_decl = parent_block.src_decl,
26626 .namespace = parent_block.namespace,26612 .namespace = parent_block.namespace,
26627 .wip_capture_scope = parent_block.wip_capture_scope,
26628 .instructions = .{},26613 .instructions = .{},
26629 .inlining = parent_block.inlining,26614 .inlining = parent_block.inlining,
26630 .is_comptime = false,26615 .is_comptime = false,
...@@ -26741,7 +26726,6 @@ fn safetyCheckFormatted(...@@ -26741,7 +26726,6 @@ fn safetyCheckFormatted(
26741 .sema = sema,26726 .sema = sema,
26742 .src_decl = parent_block.src_decl,26727 .src_decl = parent_block.src_decl,
26743 .namespace = parent_block.namespace,26728 .namespace = parent_block.namespace,
26744 .wip_capture_scope = parent_block.wip_capture_scope,
26745 .instructions = .{},26729 .instructions = .{},
26746 .inlining = parent_block.inlining,26730 .inlining = parent_block.inlining,
26747 .is_comptime = false,26731 .is_comptime = false,
...@@ -35766,7 +35750,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp...@@ -35766,7 +35750,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
35766 .sema = &sema,35750 .sema = &sema,
35767 .src_decl = decl_index,35751 .src_decl = decl_index,
35768 .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace,35752 .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace,
35769 .wip_capture_scope = try mod.createCaptureScope(decl.src_scope),
35770 .instructions = .{},35753 .instructions = .{},
35771 .inlining = null,35754 .inlining = null,
35772 .is_comptime = true,35755 .is_comptime = true,
...@@ -35789,9 +35772,16 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp...@@ -35789,9 +35772,16 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp
3578935772
35790 if (small.has_backing_int) {35773 if (small.has_backing_int) {
35791 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len;35774 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len;
35775 const captures_len = if (small.has_captures_len) blk: {
35776 const captures_len = zir.extra[extra_index];
35777 extra_index += 1;
35778 break :blk captures_len;
35779 } else 0;
35792 extra_index += @intFromBool(small.has_fields_len);35780 extra_index += @intFromBool(small.has_fields_len);
35793 extra_index += @intFromBool(small.has_decls_len);35781 extra_index += @intFromBool(small.has_decls_len);
3579435782
35783 extra_index += captures_len;
35784
35795 const backing_int_body_len = zir.extra[extra_index];35785 const backing_int_body_len = zir.extra[extra_index];
35796 extra_index += 1;35786 extra_index += 1;
3579735787
...@@ -36500,6 +36490,12 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {...@@ -36500,6 +36490,12 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {
36500 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);36490 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
36501 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len;36491 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).Struct.fields.len;
3650236492
36493 const captures_len = if (small.has_captures_len) blk: {
36494 const captures_len = zir.extra[extra_index];
36495 extra_index += 1;
36496 break :blk captures_len;
36497 } else 0;
36498
36503 const fields_len = if (small.has_fields_len) blk: {36499 const fields_len = if (small.has_fields_len) blk: {
36504 const fields_len = zir.extra[extra_index];36500 const fields_len = zir.extra[extra_index];
36505 extra_index += 1;36501 extra_index += 1;
...@@ -36512,6 +36508,8 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {...@@ -36512,6 +36508,8 @@ fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {
36512 break :decls_len decls_len;36508 break :decls_len decls_len;
36513 } else 0;36509 } else 0;
3651436510
36511 extra_index += captures_len;
36512
36515 // The backing integer cannot be handled until `resolveStructLayout()`.36513 // The backing integer cannot be handled until `resolveStructLayout()`.
36516 if (small.has_backing_int) {36514 if (small.has_backing_int) {
36517 const backing_int_body_len = zir.extra[extra_index];36515 const backing_int_body_len = zir.extra[extra_index];
...@@ -36584,7 +36582,6 @@ fn semaStructFields(...@@ -36584,7 +36582,6 @@ fn semaStructFields(
36584 .sema = &sema,36582 .sema = &sema,
36585 .src_decl = decl_index,36583 .src_decl = decl_index,
36586 .namespace = namespace_index,36584 .namespace = namespace_index,
36587 .wip_capture_scope = try mod.createCaptureScope(decl.src_scope),
36588 .instructions = .{},36585 .instructions = .{},
36589 .inlining = null,36586 .inlining = null,
36590 .is_comptime = true,36587 .is_comptime = true,
...@@ -36842,7 +36839,6 @@ fn semaStructFieldInits(...@@ -36842,7 +36839,6 @@ fn semaStructFieldInits(
36842 .sema = &sema,36839 .sema = &sema,
36843 .src_decl = decl_index,36840 .src_decl = decl_index,
36844 .namespace = namespace_index,36841 .namespace = namespace_index,
36845 .wip_capture_scope = try mod.createCaptureScope(decl.src_scope),
36846 .instructions = .{},36842 .instructions = .{},
36847 .inlining = null,36843 .inlining = null,
36848 .is_comptime = true,36844 .is_comptime = true,
...@@ -36974,6 +36970,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -36974,6 +36970,12 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
36974 break :blk ty_ref;36970 break :blk ty_ref;
36975 } else .none;36971 } else .none;
3697636972
36973 const captures_len = if (small.has_captures_len) blk: {
36974 const captures_len = zir.extra[extra_index];
36975 extra_index += 1;
36976 break :blk captures_len;
36977 } else 0;
36978
36977 const body_len = if (small.has_body_len) blk: {36979 const body_len = if (small.has_body_len) blk: {
36978 const body_len = zir.extra[extra_index];36980 const body_len = zir.extra[extra_index];
36979 extra_index += 1;36981 extra_index += 1;
...@@ -36992,8 +36994,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -36992,8 +36994,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
36992 break :decls_len decls_len;36994 break :decls_len decls_len;
36993 } else 0;36995 } else 0;
3699436996
36995 // Skip over decls.36997 // Skip over captures and decls.
36996 extra_index += decls_len;36998 extra_index += captures_len + decls_len;
3699736999
36998 const body = zir.bodySlice(extra_index, body_len);37000 const body = zir.bodySlice(extra_index, body_len);
36999 extra_index += body.len;37001 extra_index += body.len;
...@@ -37028,7 +37030,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un...@@ -37028,7 +37030,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un
37028 .sema = &sema,37030 .sema = &sema,
37029 .src_decl = decl_index,37031 .src_decl = decl_index,
37030 .namespace = union_type.namespace,37032 .namespace = union_type.namespace,
37031 .wip_capture_scope = try mod.createCaptureScope(decl.src_scope),
37032 .instructions = .{},37033 .instructions = .{},
37033 .inlining = null,37034 .inlining = null,
37034 .is_comptime = true,37035 .is_comptime = true,
...@@ -37372,7 +37373,7 @@ fn generateUnionTagTypeNumbered(...@@ -37372,7 +37373,7 @@ fn generateUnionTagTypeNumbered(
37372 const ip = &mod.intern_pool;37373 const ip = &mod.intern_pool;
3737337374
37374 const src_decl = mod.declPtr(block.src_decl);37375 const src_decl = mod.declPtr(block.src_decl);
37375 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);37376 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node);
37376 errdefer mod.destroyDecl(new_decl_index);37377 errdefer mod.destroyDecl(new_decl_index);
37377 const fqn = try decl.fullyQualifiedName(mod);37378 const fqn = try decl.fullyQualifiedName(mod);
37378 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});37379 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
...@@ -37425,7 +37426,7 @@ fn generateUnionTagTypeSimple(...@@ -37425,7 +37426,7 @@ fn generateUnionTagTypeSimple(
37425 };37426 };
37426 const fqn = try mod.declPtr(decl_index).fullyQualifiedName(mod);37427 const fqn = try mod.declPtr(decl_index).fullyQualifiedName(mod);
37427 const src_decl = mod.declPtr(block.src_decl);37428 const src_decl = mod.declPtr(block.src_decl);
37428 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);37429 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node);
37429 errdefer mod.destroyDecl(new_decl_index);37430 errdefer mod.destroyDecl(new_decl_index);
37430 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});37431 const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)});
37431 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{37432 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
...@@ -37460,7 +37461,6 @@ fn generateUnionTagTypeSimple(...@@ -37460,7 +37461,6 @@ fn generateUnionTagTypeSimple(
37460}37461}
3746137462
37462fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {37463fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
37463 const mod = sema.mod;
37464 const gpa = sema.gpa;37464 const gpa = sema.gpa;
37465 const src = LazySrcLoc.nodeOffset(0);37465 const src = LazySrcLoc.nodeOffset(0);
3746637466
...@@ -37469,7 +37469,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {...@@ -37469,7 +37469,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
37469 .sema = sema,37469 .sema = sema,
37470 .src_decl = sema.owner_decl_index,37470 .src_decl = sema.owner_decl_index,
37471 .namespace = sema.owner_decl.src_namespace,37471 .namespace = sema.owner_decl.src_namespace,
37472 .wip_capture_scope = try mod.createCaptureScope(sema.owner_decl.src_scope),
37473 .instructions = .{},37472 .instructions = .{},
37474 .inlining = null,37473 .inlining = null,
37475 .is_comptime = true,37474 .is_comptime = true,
...@@ -37510,7 +37509,6 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int...@@ -37510,7 +37509,6 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int
37510}37509}
3751137510
37512fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {37511fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
37513 const mod = sema.mod;
37514 const ty_inst = try sema.getBuiltin(name);37512 const ty_inst = try sema.getBuiltin(name);
3751537513
37516 var block: Block = .{37514 var block: Block = .{
...@@ -37518,7 +37516,6 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -37518,7 +37516,6 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
37518 .sema = sema,37516 .sema = sema,
37519 .src_decl = sema.owner_decl_index,37517 .src_decl = sema.owner_decl_index,
37520 .namespace = sema.owner_decl.src_namespace,37518 .namespace = sema.owner_decl.src_namespace,
37521 .wip_capture_scope = try mod.createCaptureScope(sema.owner_decl.src_scope),
37522 .instructions = .{},37519 .instructions = .{},
37523 .inlining = null,37520 .inlining = null,
37524 .is_comptime = true,37521 .is_comptime = true,
src/print_zir.zig+96-5
...@@ -282,7 +282,6 @@ const Writer = struct {...@@ -282,7 +282,6 @@ const Writer = struct {
282282
283 .ref,283 .ref,
284 .ret_implicit,284 .ret_implicit,
285 .closure_capture,
286 .validate_ref_ty,285 .validate_ref_ty,
287 => try self.writeUnTok(stream, inst),286 => try self.writeUnTok(stream, inst),
288287
...@@ -510,8 +509,6 @@ const Writer = struct {...@@ -510,8 +509,6 @@ const Writer = struct {
510509
511 .dbg_stmt => try self.writeDbgStmt(stream, inst),510 .dbg_stmt => try self.writeDbgStmt(stream, inst),
512511
513 .closure_get => try self.writeInstNode(stream, inst),
514
515 .@"defer" => try self.writeDefer(stream, inst),512 .@"defer" => try self.writeDefer(stream, inst),
516 .defer_err_code => try self.writeDeferErrCode(stream, inst),513 .defer_err_code => try self.writeDeferErrCode(stream, inst),
517514
...@@ -611,6 +608,7 @@ const Writer = struct {...@@ -611,6 +608,7 @@ const Writer = struct {
611 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),608 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
612609
613 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),610 .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),
611 .closure_get => try self.writeClosureGet(stream, extended),
614 }612 }
615 }613 }
616614
...@@ -1401,6 +1399,12 @@ const Writer = struct {...@@ -1401,6 +1399,12 @@ const Writer = struct {
14011399
1402 var extra_index: usize = extra.end;1400 var extra_index: usize = extra.end;
14031401
1402 const captures_len = if (small.has_captures_len) blk: {
1403 const captures_len = self.code.extra[extra_index];
1404 extra_index += 1;
1405 break :blk captures_len;
1406 } else 0;
1407
1404 const fields_len = if (small.has_fields_len) blk: {1408 const fields_len = if (small.has_fields_len) blk: {
1405 const fields_len = self.code.extra[extra_index];1409 const fields_len = self.code.extra[extra_index];
1406 extra_index += 1;1410 extra_index += 1;
...@@ -1419,12 +1423,26 @@ const Writer = struct {...@@ -1419,12 +1423,26 @@ const Writer = struct {
14191423
1420 try stream.print("{s}, ", .{@tagName(small.name_strategy)});1424 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
14211425
1422 if (small.layout == .Packed and small.has_backing_int) {1426 if (captures_len == 0) {
1427 try stream.writeAll("{}, ");
1428 } else {
1429 try stream.writeAll("{ ");
1430 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1431 extra_index += 1;
1432 for (1..captures_len) |_| {
1433 try stream.writeAll(", ");
1434 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1435 extra_index += 1;
1436 }
1437 try stream.writeAll(" }, ");
1438 }
1439
1440 if (small.has_backing_int) {
1423 const backing_int_body_len = self.code.extra[extra_index];1441 const backing_int_body_len = self.code.extra[extra_index];
1424 extra_index += 1;1442 extra_index += 1;
1425 try stream.writeAll("Packed(");1443 try stream.writeAll("Packed(");
1426 if (backing_int_body_len == 0) {1444 if (backing_int_body_len == 0) {
1427 const backing_int_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index]));1445 const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]);
1428 extra_index += 1;1446 extra_index += 1;
1429 try self.writeInstRef(stream, backing_int_ref);1447 try self.writeInstRef(stream, backing_int_ref);
1430 } else {1448 } else {
...@@ -1601,6 +1619,12 @@ const Writer = struct {...@@ -1601,6 +1619,12 @@ const Writer = struct {
1601 break :blk tag_type_ref;1619 break :blk tag_type_ref;
1602 } else .none;1620 } else .none;
16031621
1622 const captures_len = if (small.has_captures_len) blk: {
1623 const captures_len = self.code.extra[extra_index];
1624 extra_index += 1;
1625 break :blk captures_len;
1626 } else 0;
1627
1604 const body_len = if (small.has_body_len) blk: {1628 const body_len = if (small.has_body_len) blk: {
1605 const body_len = self.code.extra[extra_index];1629 const body_len = self.code.extra[extra_index];
1606 extra_index += 1;1630 extra_index += 1;
...@@ -1624,6 +1648,20 @@ const Writer = struct {...@@ -1624,6 +1648,20 @@ const Writer = struct {
1624 });1648 });
1625 try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag);1649 try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag);
16261650
1651 if (captures_len == 0) {
1652 try stream.writeAll("{}, ");
1653 } else {
1654 try stream.writeAll("{ ");
1655 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1656 extra_index += 1;
1657 for (1..captures_len) |_| {
1658 try stream.writeAll(", ");
1659 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1660 extra_index += 1;
1661 }
1662 try stream.writeAll(" }, ");
1663 }
1664
1627 if (decls_len == 0) {1665 if (decls_len == 0) {
1628 try stream.writeAll("{}");1666 try stream.writeAll("{}");
1629 } else {1667 } else {
...@@ -1748,6 +1786,12 @@ const Writer = struct {...@@ -1748,6 +1786,12 @@ const Writer = struct {
1748 break :blk tag_type_ref;1786 break :blk tag_type_ref;
1749 } else .none;1787 } else .none;
17501788
1789 const captures_len = if (small.has_captures_len) blk: {
1790 const captures_len = self.code.extra[extra_index];
1791 extra_index += 1;
1792 break :blk captures_len;
1793 } else 0;
1794
1751 const body_len = if (small.has_body_len) blk: {1795 const body_len = if (small.has_body_len) blk: {
1752 const body_len = self.code.extra[extra_index];1796 const body_len = self.code.extra[extra_index];
1753 extra_index += 1;1797 extra_index += 1;
...@@ -1769,6 +1813,20 @@ const Writer = struct {...@@ -1769,6 +1813,20 @@ const Writer = struct {
1769 try stream.print("{s}, ", .{@tagName(small.name_strategy)});1813 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
1770 try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive);1814 try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive);
17711815
1816 if (captures_len == 0) {
1817 try stream.writeAll("{}, ");
1818 } else {
1819 try stream.writeAll("{ ");
1820 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1821 extra_index += 1;
1822 for (1..captures_len) |_| {
1823 try stream.writeAll(", ");
1824 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1825 extra_index += 1;
1826 }
1827 try stream.writeAll(" }, ");
1828 }
1829
1772 if (decls_len == 0) {1830 if (decls_len == 0) {
1773 try stream.writeAll("{}, ");1831 try stream.writeAll("{}, ");
1774 } else {1832 } else {
...@@ -1854,6 +1912,12 @@ const Writer = struct {...@@ -1854,6 +1912,12 @@ const Writer = struct {
1854 const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand);1912 const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand);
1855 var extra_index: usize = extra.end;1913 var extra_index: usize = extra.end;
18561914
1915 const captures_len = if (small.has_captures_len) blk: {
1916 const captures_len = self.code.extra[extra_index];
1917 extra_index += 1;
1918 break :blk captures_len;
1919 } else 0;
1920
1857 const decls_len = if (small.has_decls_len) blk: {1921 const decls_len = if (small.has_decls_len) blk: {
1858 const decls_len = self.code.extra[extra_index];1922 const decls_len = self.code.extra[extra_index];
1859 extra_index += 1;1923 extra_index += 1;
...@@ -1862,6 +1926,20 @@ const Writer = struct {...@@ -1862,6 +1926,20 @@ const Writer = struct {
18621926
1863 try stream.print("{s}, ", .{@tagName(small.name_strategy)});1927 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
18641928
1929 if (captures_len == 0) {
1930 try stream.writeAll("{}, ");
1931 } else {
1932 try stream.writeAll("{ ");
1933 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1934 extra_index += 1;
1935 for (1..captures_len) |_| {
1936 try stream.writeAll(", ");
1937 try self.writeCapture(stream, @enumFromInt(self.code.extra[extra_index]));
1938 extra_index += 1;
1939 }
1940 try stream.writeAll(" }, ");
1941 }
1942
1865 if (decls_len == 0) {1943 if (decls_len == 0) {
1866 try stream.writeAll("{})");1944 try stream.writeAll("{})");
1867 } else {1945 } else {
...@@ -2706,6 +2784,12 @@ const Writer = struct {...@@ -2706,6 +2784,12 @@ const Writer = struct {
2706 try self.writeSrc(stream, inst_data.src());2784 try self.writeSrc(stream, inst_data.src());
2707 }2785 }
27082786
2787 fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
2788 const src = LazySrcLoc.nodeOffset(@bitCast(extended.operand));
2789 try stream.print("{d})) ", .{extended.small});
2790 try self.writeSrc(stream, src);
2791 }
2792
2709 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {2793 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {
2710 if (ref == .none) {2794 if (ref == .none) {
2711 return stream.writeAll(".none");2795 return stream.writeAll(".none");
...@@ -2722,6 +2806,13 @@ const Writer = struct {...@@ -2722,6 +2806,13 @@ const Writer = struct {
2722 return stream.print("%{d}", .{@intFromEnum(inst)});2806 return stream.print("%{d}", .{@intFromEnum(inst)});
2723 }2807 }
27242808
2809 fn writeCapture(self: *Writer, stream: anytype, capture: Zir.Inst.Capture) !void {
2810 switch (capture.unwrap()) {
2811 .inst => |inst| return self.writeInstIndex(stream, inst),
2812 .nested => |i| return stream.print("[{d}]", .{i}),
2813 }
2814 }
2815
2725 fn writeOptionalInstRef(2816 fn writeOptionalInstRef(
2726 self: *Writer,2817 self: *Writer,
2727 stream: anytype,2818 stream: anytype,