| ... | ... | @@ -889,17 +889,18 @@ fn analyzeBodyInner( |
| 889 | 889 | |
| 890 | 890 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); |
| 891 | 891 | |
| 892 | // Most of the time, we don't need to construct a new capture scope for a |
| 893 | // block. However, successive iterations of comptime loops can capture |
| 894 | // different values for the same Zir.Inst.Index, so in those cases, we will |
| 895 | // have to create nested capture scopes; see the `.repeat` case below. |
| 892 | 896 | const parent_capture_scope = block.wip_capture_scope; |
| 893 | | |
| 894 | | var wip_captures = WipCaptureScope{ |
| 895 | | .finalized = true, |
| 897 | parent_capture_scope.incRef(); |
| 898 | var wip_captures: WipCaptureScope = .{ |
| 896 | 899 | .scope = parent_capture_scope, |
| 897 | | .perm_arena = sema.perm_arena, |
| 898 | 900 | .gpa = sema.gpa, |
| 901 | .finalized = true, // don't finalize the parent scope |
| 899 | 902 | }; |
| 900 | | defer if (wip_captures.scope != parent_capture_scope) { |
| 901 | | wip_captures.deinit(); |
| 902 | | }; |
| 903 | defer wip_captures.deinit(); |
| 903 | 904 | |
| 904 | 905 | const mod = sema.mod; |
| 905 | 906 | const map = &sema.inst_map; |
| ... | ... | @@ -1452,6 +1453,11 @@ fn analyzeBodyInner( |
| 1452 | 1453 | const src = LazySrcLoc.nodeOffset(datas[inst].node); |
| 1453 | 1454 | try sema.emitBackwardBranch(block, src); |
| 1454 | 1455 | if (wip_captures.scope.captures.count() != orig_captures) { |
| 1456 | // We need to construct new capture scopes for the next loop iteration so it |
| 1457 | // can capture values without clobbering the earlier iteration's captures. |
| 1458 | // At first, we reused the parent capture scope as an optimization, but for |
| 1459 | // successive scopes we have to create new ones as children of the parent |
| 1460 | // scope. |
| 1455 | 1461 | try wip_captures.reset(parent_capture_scope); |
| 1456 | 1462 | block.wip_capture_scope = wip_captures.scope; |
| 1457 | 1463 | orig_captures = 0; |
| ... | ... | @@ -1467,6 +1473,11 @@ fn analyzeBodyInner( |
| 1467 | 1473 | const src = LazySrcLoc.nodeOffset(datas[inst].node); |
| 1468 | 1474 | try sema.emitBackwardBranch(block, src); |
| 1469 | 1475 | if (wip_captures.scope.captures.count() != orig_captures) { |
| 1476 | // We need to construct new capture scopes for the next loop iteration so it |
| 1477 | // can capture values without clobbering the earlier iteration's captures. |
| 1478 | // At first, we reused the parent capture scope as an optimization, but for |
| 1479 | // successive scopes we have to create new ones as children of the parent |
| 1480 | // scope. |
| 1470 | 1481 | try wip_captures.reset(parent_capture_scope); |
| 1471 | 1482 | block.wip_capture_scope = wip_captures.scope; |
| 1472 | 1483 | orig_captures = 0; |
| ... | ... | @@ -1749,6 +1760,8 @@ fn analyzeBodyInner( |
| 1749 | 1760 | if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some); |
| 1750 | 1761 | |
| 1751 | 1762 | if (!wip_captures.finalized) { |
| 1763 | // We've updated the capture scope due to a `repeat` instruction where |
| 1764 | // the body had a capture; finalize our child scope and reset |
| 1752 | 1765 | try wip_captures.finalize(); |
| 1753 | 1766 | block.wip_capture_scope = parent_capture_scope; |
| 1754 | 1767 | } |
| ... | ... | @@ -3007,7 +3020,7 @@ fn zirEnumDecl( |
| 3007 | 3020 | defer sema.func = prev_func; |
| 3008 | 3021 | defer sema.func_index = prev_func_index; |
| 3009 | 3022 | |
| 3010 | | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope); |
| 3023 | var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope); |
| 3011 | 3024 | defer wip_captures.deinit(); |
| 3012 | 3025 | |
| 3013 | 3026 | var enum_block: Block = .{ |
| ... | ... | @@ -6888,7 +6901,7 @@ fn analyzeCall( |
| 6888 | 6901 | sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index; |
| 6889 | 6902 | defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index; |
| 6890 | 6903 | |
| 6891 | | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, fn_owner_decl.src_scope); |
| 6904 | var wip_captures = try WipCaptureScope.init(gpa, fn_owner_decl.src_scope); |
| 6892 | 6905 | defer wip_captures.deinit(); |
| 6893 | 6906 | |
| 6894 | 6907 | var child_block: Block = .{ |
| ... | ... | @@ -7751,7 +7764,7 @@ fn resolveGenericInstantiationType( |
| 7751 | 7764 | }; |
| 7752 | 7765 | defer child_sema.deinit(); |
| 7753 | 7766 | |
| 7754 | | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope); |
| 7767 | var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope); |
| 7755 | 7768 | defer wip_captures.deinit(); |
| 7756 | 7769 | |
| 7757 | 7770 | var child_block: Block = .{ |
| ... | ... | @@ -11151,7 +11164,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11151 | 11164 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 11152 | 11165 | extra_index += body_len; |
| 11153 | 11166 | |
| 11154 | | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope); |
| 11167 | var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope); |
| 11155 | 11168 | defer wip_captures.deinit(); |
| 11156 | 11169 | |
| 11157 | 11170 | case_block.instructions.shrinkRetainingCapacity(0); |
| ... | ... | @@ -11396,7 +11409,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11396 | 11409 | var cond_body = try case_block.instructions.toOwnedSlice(gpa); |
| 11397 | 11410 | defer gpa.free(cond_body); |
| 11398 | 11411 | |
| 11399 | | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope); |
| 11412 | var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope); |
| 11400 | 11413 | defer wip_captures.deinit(); |
| 11401 | 11414 | |
| 11402 | 11415 | case_block.instructions.shrinkRetainingCapacity(0); |
| ... | ... | @@ -11577,7 +11590,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 11577 | 11590 | }), |
| 11578 | 11591 | }; |
| 11579 | 11592 | |
| 11580 | | var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope); |
| 11593 | var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope); |
| 11581 | 11594 | defer wip_captures.deinit(); |
| 11582 | 11595 | |
| 11583 | 11596 | case_block.instructions.shrinkRetainingCapacity(0); |
| ... | ... | @@ -15720,13 +15733,15 @@ fn zirClosureCapture( |
| 15720 | 15733 | // ...in which case the closure_capture instruction has access to a runtime |
| 15721 | 15734 | // value only. In such case we preserve the type and use a dummy runtime value. |
| 15722 | 15735 | const operand = try sema.resolveInst(inst_data.operand); |
| 15723 | | const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse |
| 15724 | | Value.@"unreachable"; |
| 15725 | | |
| 15726 | | try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{ |
| 15727 | | .ty = sema.typeOf(operand), |
| 15728 | | .val = try val.copy(sema.perm_arena), |
| 15729 | | }); |
| 15736 | const ty = sema.typeOf(operand); |
| 15737 | const capture: CaptureScope.Capture = blk: { |
| 15738 | if (try sema.resolveMaybeUndefValAllowVariables(operand)) |val| { |
| 15739 | const ip_index = try val.intern(ty, sema.mod); |
| 15740 | break :blk .{ .comptime_val = ip_index }; |
| 15741 | } |
| 15742 | break :blk .{ .runtime_val = ty.toIntern() }; |
| 15743 | }; |
| 15744 | try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, capture); |
| 15730 | 15745 | } |
| 15731 | 15746 | |
| 15732 | 15747 | fn zirClosureGet( |
| ... | ... | @@ -15740,7 +15755,7 @@ fn zirClosureGet( |
| 15740 | 15755 | var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?; |
| 15741 | 15756 | // Note: The target closure must be in this scope list. |
| 15742 | 15757 | // If it's not here, the zir is invalid, or the list is broken. |
| 15743 | | const tv = while (true) { |
| 15758 | const capture = while (true) { |
| 15744 | 15759 | // Note: We don't need to add a dependency here, because |
| 15745 | 15760 | // decls always depend on their lexical parents. |
| 15746 | 15761 | |
| ... | ... | @@ -15753,13 +15768,13 @@ fn zirClosureGet( |
| 15753 | 15768 | } |
| 15754 | 15769 | return error.AnalysisFail; |
| 15755 | 15770 | } |
| 15756 | | if (scope.captures.getPtr(inst_data.inst)) |tv| { |
| 15757 | | break tv; |
| 15771 | if (scope.captures.get(inst_data.inst)) |capture| { |
| 15772 | break capture; |
| 15758 | 15773 | } |
| 15759 | 15774 | scope = scope.parent.?; |
| 15760 | 15775 | }; |
| 15761 | 15776 | |
| 15762 | | if (tv.val.toIntern() == .unreachable_value and !block.is_typeof and sema.func_index == .none) { |
| 15777 | if (capture == .runtime_val and !block.is_typeof and sema.func_index == .none) { |
| 15763 | 15778 | const msg = msg: { |
| 15764 | 15779 | const name = name: { |
| 15765 | 15780 | const file = sema.owner_decl.getFileScope(mod); |
| ... | ... | @@ -15787,7 +15802,7 @@ fn zirClosureGet( |
| 15787 | 15802 | return sema.failWithOwnedErrorMsg(msg); |
| 15788 | 15803 | } |
| 15789 | 15804 | |
| 15790 | | if (tv.val.toIntern() == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func_index != .none) { |
| 15805 | if (capture == .runtime_val and !block.is_typeof and !block.is_comptime and sema.func_index != .none) { |
| 15791 | 15806 | const msg = msg: { |
| 15792 | 15807 | const name = name: { |
| 15793 | 15808 | const file = sema.owner_decl.getFileScope(mod); |
| ... | ... | @@ -15817,13 +15832,17 @@ fn zirClosureGet( |
| 15817 | 15832 | return sema.failWithOwnedErrorMsg(msg); |
| 15818 | 15833 | } |
| 15819 | 15834 | |
| 15820 | | if (tv.val.toIntern() == .unreachable_value) { |
| 15821 | | assert(block.is_typeof); |
| 15822 | | // We need a dummy runtime instruction with the correct type. |
| 15823 | | return block.addTy(.alloc, tv.ty); |
| 15835 | switch (capture) { |
| 15836 | .runtime_val => |ty_ip_index| { |
| 15837 | assert(block.is_typeof); |
| 15838 | // We need a dummy runtime instruction with the correct type. |
| 15839 | return block.addTy(.alloc, ty_ip_index.toType()); |
| 15840 | }, |
| 15841 | .comptime_val => |val_ip_index| { |
| 15842 | const ty = mod.intern_pool.typeOf(val_ip_index).toType(); |
| 15843 | return sema.addConstant(ty, val_ip_index.toValue()); |
| 15844 | }, |
| 15824 | 15845 | } |
| 15825 | | |
| 15826 | | return sema.addConstant(tv.ty, tv.val); |
| 15827 | 15846 | } |
| 15828 | 15847 | |
| 15829 | 15848 | fn zirRetAddr( |
| ... | ... | @@ -31838,7 +31857,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 31838 | 31857 | var sema: Sema = .{ .mod = mod, .gpa = gpa, .arena = analysis_arena.allocator(), .perm_arena = decl_arena_allocator, .code = zir, .owner_decl = decl, .owner_decl_index = decl_index, .func = null, .func_index = .none, .fn_ret_ty = Type.void, .owner_func = null, .owner_func_index = .none }; |
| 31839 | 31858 | defer sema.deinit(); |
| 31840 | 31859 | |
| 31841 | | var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope); |
| 31860 | var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope); |
| 31842 | 31861 | defer wip_captures.deinit(); |
| 31843 | 31862 | |
| 31844 | 31863 | var block: Block = .{ |
| ... | ... | @@ -32591,7 +32610,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 32591 | 32610 | }; |
| 32592 | 32611 | defer sema.deinit(); |
| 32593 | 32612 | |
| 32594 | | var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope); |
| 32613 | var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope); |
| 32595 | 32614 | defer wip_captures.deinit(); |
| 32596 | 32615 | |
| 32597 | 32616 | var block_scope: Block = .{ |
| ... | ... | @@ -32933,7 +32952,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 32933 | 32952 | }; |
| 32934 | 32953 | defer sema.deinit(); |
| 32935 | 32954 | |
| 32936 | | var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope); |
| 32955 | var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope); |
| 32937 | 32956 | defer wip_captures.deinit(); |
| 32938 | 32957 | |
| 32939 | 32958 | var block_scope: Block = .{ |
| ... | ... | @@ -33360,7 +33379,7 @@ fn generateUnionTagTypeSimple( |
| 33360 | 33379 | } |
| 33361 | 33380 | |
| 33362 | 33381 | fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 33363 | | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.perm_arena, sema.owner_decl.src_scope); |
| 33382 | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.owner_decl.src_scope); |
| 33364 | 33383 | defer wip_captures.deinit(); |
| 33365 | 33384 | |
| 33366 | 33385 | var block: Block = .{ |
| ... | ... | @@ -33405,7 +33424,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref { |
| 33405 | 33424 | fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type { |
| 33406 | 33425 | const ty_inst = try sema.getBuiltin(name); |
| 33407 | 33426 | |
| 33408 | | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.perm_arena, sema.owner_decl.src_scope); |
| 33427 | var wip_captures = try WipCaptureScope.init(sema.gpa, sema.owner_decl.src_scope); |
| 33409 | 33428 | defer wip_captures.deinit(); |
| 33410 | 33429 | |
| 33411 | 33430 | var block: Block = .{ |