| ... | ... | @@ -34,6 +34,7 @@ func_index: InternPool.Index, |
| 34 | 34 | func_is_naked: bool, |
| 35 | 35 | /// Used to restore the error return trace when returning a non-error from a function. |
| 36 | 36 | error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none, |
| 37 | comptime_err_ret_trace: *std.ArrayList(Module.SrcLoc), |
| 37 | 38 | /// When semantic analysis needs to know the return type of the function whose body |
| 38 | 39 | /// is being analyzed, this `Type` should be used instead of going through `func`. |
| 39 | 40 | /// This will correctly handle the case of a comptime/inline function call of a |
| ... | ... | @@ -1569,7 +1570,22 @@ fn analyzeBodyInner( |
| 1569 | 1570 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 1570 | 1571 | const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); |
| 1571 | 1572 | const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 1572 | | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1573 | |
| 1574 | // Create a temporary child block so that this loop is properly |
| 1575 | // labeled for any .restore_err_ret_index instructions |
| 1576 | var child_block = block.makeSubBlock(); |
| 1577 | |
| 1578 | var label: Block.Label = .{ |
| 1579 | .zir_block = inst, |
| 1580 | .merges = undefined, |
| 1581 | }; |
| 1582 | child_block.label = &label; |
| 1583 | |
| 1584 | // Write these instructions directly into the parent block |
| 1585 | child_block.instructions = block.instructions; |
| 1586 | defer block.instructions = child_block.instructions; |
| 1587 | |
| 1588 | const break_data = (try sema.analyzeBodyBreak(&child_block, inline_body)) orelse |
| 1573 | 1589 | break always_noreturn; |
| 1574 | 1590 | if (inst == break_data.block_inst) { |
| 1575 | 1591 | break :blk try sema.resolveInst(break_data.operand); |
| ... | ... | @@ -1585,13 +1601,22 @@ fn analyzeBodyInner( |
| 1585 | 1601 | const inst_data = datas[@intFromEnum(inst)].pl_node; |
| 1586 | 1602 | const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); |
| 1587 | 1603 | const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 1588 | | // If this block contains a function prototype, we need to reset the |
| 1589 | | // current list of parameters and restore it later. |
| 1590 | | // Note: this probably needs to be resolved in a more general manner. |
| 1591 | | const prev_params = block.params; |
| 1592 | | block.params = .{}; |
| 1593 | | defer block.params = prev_params; |
| 1594 | | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| 1604 | |
| 1605 | // Create a temporary child block so that this block is properly |
| 1606 | // labeled for any .restore_err_ret_index instructions |
| 1607 | var child_block = block.makeSubBlock(); |
| 1608 | |
| 1609 | var label: Block.Label = .{ |
| 1610 | .zir_block = inst, |
| 1611 | .merges = undefined, |
| 1612 | }; |
| 1613 | child_block.label = &label; |
| 1614 | |
| 1615 | // Write these instructions directly into the parent block |
| 1616 | child_block.instructions = block.instructions; |
| 1617 | defer block.instructions = child_block.instructions; |
| 1618 | |
| 1619 | const break_data = (try sema.analyzeBodyBreak(&child_block, inline_body)) orelse |
| 1595 | 1620 | break always_noreturn; |
| 1596 | 1621 | if (inst == break_data.block_inst) { |
| 1597 | 1622 | break :blk try sema.resolveInst(break_data.operand); |
| ... | ... | @@ -2379,6 +2404,25 @@ fn typeSupportsFieldAccess(mod: *const Module, ty: Type, field_name: InternPool. |
| 2379 | 2404 | } |
| 2380 | 2405 | } |
| 2381 | 2406 | |
| 2407 | fn failWithComptimeErrorRetTrace( |
| 2408 | sema: *Sema, |
| 2409 | block: *Block, |
| 2410 | src: LazySrcLoc, |
| 2411 | name: InternPool.NullTerminatedString, |
| 2412 | ) CompileError { |
| 2413 | const mod = sema.mod; |
| 2414 | const msg = msg: { |
| 2415 | const msg = try sema.errMsg(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)}); |
| 2416 | errdefer msg.destroy(sema.gpa); |
| 2417 | |
| 2418 | for (sema.comptime_err_ret_trace.items) |src_loc| { |
| 2419 | try mod.errNoteNonLazy(src_loc, msg, "error returned here", .{}); |
| 2420 | } |
| 2421 | break :msg msg; |
| 2422 | }; |
| 2423 | return sema.failWithOwnedErrorMsg(block, msg); |
| 2424 | } |
| 2425 | |
| 2382 | 2426 | /// We don't return a pointer to the new error note because the pointer |
| 2383 | 2427 | /// becomes invalid when you add another one. |
| 2384 | 2428 | fn errNote( |
| ... | ... | @@ -6534,10 +6578,12 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref |
| 6534 | 6578 | const gpa = sema.gpa; |
| 6535 | 6579 | const src = sema.src; |
| 6536 | 6580 | |
| 6537 | | if (!block.ownerModule().error_tracing) return .none; |
| 6581 | if (block.is_comptime or block.is_typeof) { |
| 6582 | const index_val = try mod.intValue_u64(Type.usize, sema.comptime_err_ret_trace.items.len); |
| 6583 | return Air.internedToRef(index_val.toIntern()); |
| 6584 | } |
| 6538 | 6585 | |
| 6539 | | if (block.is_comptime) |
| 6540 | | return .none; |
| 6586 | if (!block.ownerModule().error_tracing) return .none; |
| 6541 | 6587 | |
| 6542 | 6588 | const stack_trace_ty = sema.getBuiltinType("StackTrace") catch |err| switch (err) { |
| 6543 | 6589 | error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, |
| ... | ... | @@ -7498,6 +7544,14 @@ fn analyzeCall( |
| 7498 | 7544 | try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src); |
| 7499 | 7545 | } |
| 7500 | 7546 | |
| 7547 | if (is_comptime_call or block.is_typeof) { |
| 7548 | // Save the error trace as our first action in the function |
| 7549 | // to match the behavior of runtime function calls. |
| 7550 | const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); |
| 7551 | sema.error_return_trace_index_on_fn_entry = error_return_trace_index; |
| 7552 | child_block.error_return_trace_index = error_return_trace_index; |
| 7553 | } |
| 7554 | |
| 7501 | 7555 | const result = result: { |
| 7502 | 7556 | sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { |
| 7503 | 7557 | error.ComptimeReturn => break :result inlining.comptime_result, |
| ... | ... | @@ -7858,6 +7912,7 @@ fn instantiateGenericCall( |
| 7858 | 7912 | .branch_quota = sema.branch_quota, |
| 7859 | 7913 | .branch_count = sema.branch_count, |
| 7860 | 7914 | .comptime_mutable_decls = sema.comptime_mutable_decls, |
| 7915 | .comptime_err_ret_trace = sema.comptime_err_ret_trace, |
| 7861 | 7916 | }; |
| 7862 | 7917 | defer child_sema.deinit(); |
| 7863 | 7918 | |
| ... | ... | @@ -8783,7 +8838,7 @@ fn analyzeErrUnionPayload( |
| 8783 | 8838 | const payload_ty = err_union_ty.errorUnionPayload(mod); |
| 8784 | 8839 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { |
| 8785 | 8840 | if (val.getErrorName(mod).unwrap()) |name| { |
| 8786 | | return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)}); |
| 8841 | return sema.failWithComptimeErrorRetTrace(block, src, name); |
| 8787 | 8842 | } |
| 8788 | 8843 | return Air.internedToRef(mod.intern_pool.indexToKey(val.toIntern()).error_union.val.payload); |
| 8789 | 8844 | } |
| ... | ... | @@ -8861,7 +8916,7 @@ fn analyzeErrUnionPayloadPtr( |
| 8861 | 8916 | } |
| 8862 | 8917 | if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| { |
| 8863 | 8918 | if (val.getErrorName(mod).unwrap()) |name| { |
| 8864 | | return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)}); |
| 8919 | return sema.failWithComptimeErrorRetTrace(block, src, name); |
| 8865 | 8920 | } |
| 8866 | 8921 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 8867 | 8922 | .ty = operand_pointer_ty.toIntern(), |
| ... | ... | @@ -13437,7 +13492,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I |
| 13437 | 13492 | |
| 13438 | 13493 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { |
| 13439 | 13494 | if (val.getErrorName(sema.mod).unwrap()) |name| { |
| 13440 | | return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&sema.mod.intern_pool)}); |
| 13495 | return sema.failWithComptimeErrorRetTrace(block, src, name); |
| 13441 | 13496 | } |
| 13442 | 13497 | } |
| 13443 | 13498 | } |
| ... | ... | @@ -19227,15 +19282,9 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) |
| 19227 | 19282 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].restore_err_ret_index; |
| 19228 | 19283 | const src = sema.src; // TODO |
| 19229 | 19284 | |
| 19230 | | // This is only relevant at runtime. |
| 19231 | | if (start_block.is_comptime or start_block.is_typeof) return; |
| 19232 | | |
| 19233 | 19285 | const mod = sema.mod; |
| 19234 | 19286 | const ip = &mod.intern_pool; |
| 19235 | 19287 | |
| 19236 | | if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return; |
| 19237 | | if (!start_block.ownerModule().error_tracing) return; |
| 19238 | | |
| 19239 | 19288 | const tracy = trace(@src()); |
| 19240 | 19289 | defer tracy.end(); |
| 19241 | 19290 | |
| ... | ... | @@ -19263,9 +19312,29 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) |
| 19263 | 19312 | return; // No need to restore |
| 19264 | 19313 | }; |
| 19265 | 19314 | |
| 19315 | const operand = try sema.resolveInstAllowNone(inst_data.operand); |
| 19316 | |
| 19317 | if (start_block.is_comptime or start_block.is_typeof) { |
| 19318 | const is_non_error = if (operand != .none) blk: { |
| 19319 | const is_non_error_inst = try sema.analyzeIsNonErr(start_block, src, operand); |
| 19320 | const cond_val = try sema.resolveDefinedValue(start_block, src, is_non_error_inst); |
| 19321 | break :blk cond_val.?.toBool(); |
| 19322 | } else true; // no operand means pop unconditionally |
| 19323 | |
| 19324 | if (is_non_error) return; |
| 19325 | |
| 19326 | const saved_index_val = try sema.resolveDefinedValue(start_block, src, saved_index); |
| 19327 | const saved_index_int = saved_index_val.?.toUnsignedInt(mod); |
| 19328 | assert(saved_index_int <= sema.comptime_err_ret_trace.items.len); |
| 19329 | sema.comptime_err_ret_trace.items.len = @intCast(saved_index_int); |
| 19330 | return; |
| 19331 | } |
| 19332 | |
| 19333 | if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return; |
| 19334 | if (!start_block.ownerModule().error_tracing) return; |
| 19335 | |
| 19266 | 19336 | assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere |
| 19267 | 19337 | |
| 19268 | | const operand = try sema.resolveInstAllowNone(inst_data.operand); |
| 19269 | 19338 | return sema.popErrorReturnTrace(start_block, src, operand, saved_index); |
| 19270 | 19339 | } |
| 19271 | 19340 | |
| ... | ... | @@ -19319,10 +19388,16 @@ fn analyzeRet( |
| 19319 | 19388 | |
| 19320 | 19389 | if (block.inlining) |inlining| { |
| 19321 | 19390 | if (block.is_comptime) { |
| 19322 | | _ = try sema.resolveConstValue(block, src, operand, .{ |
| 19391 | const ret_val = try sema.resolveConstValue(block, src, operand, .{ |
| 19323 | 19392 | .needed_comptime_reason = "value being returned at comptime must be comptime-known", |
| 19324 | 19393 | }); |
| 19325 | 19394 | inlining.comptime_result = operand; |
| 19395 | |
| 19396 | if (sema.fn_ret_ty.isError(mod) and ret_val.getErrorName(mod) != .none) { |
| 19397 | const src_decl = mod.declPtr(block.src_decl); |
| 19398 | const src_loc = src.toSrcLoc(src_decl, mod); |
| 19399 | try sema.comptime_err_ret_trace.append(src_loc); |
| 19400 | } |
| 19326 | 19401 | return error.ComptimeReturn; |
| 19327 | 19402 | } |
| 19328 | 19403 | // We are inlining a function call; rewrite the `ret` as a `break`. |
| ... | ... | @@ -35467,6 +35542,9 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35467 | 35542 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); |
| 35468 | 35543 | defer comptime_mutable_decls.deinit(); |
| 35469 | 35544 | |
| 35545 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 35546 | defer comptime_err_ret_trace.deinit(); |
| 35547 | |
| 35470 | 35548 | var sema: Sema = .{ |
| 35471 | 35549 | .mod = mod, |
| 35472 | 35550 | .gpa = gpa, |
| ... | ... | @@ -35480,6 +35558,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35480 | 35558 | .fn_ret_ty_ies = null, |
| 35481 | 35559 | .owner_func_index = .none, |
| 35482 | 35560 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 35561 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 35483 | 35562 | }; |
| 35484 | 35563 | defer sema.deinit(); |
| 35485 | 35564 | |
| ... | ... | @@ -36289,6 +36368,9 @@ fn semaStructFields( |
| 36289 | 36368 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); |
| 36290 | 36369 | defer comptime_mutable_decls.deinit(); |
| 36291 | 36370 | |
| 36371 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 36372 | defer comptime_err_ret_trace.deinit(); |
| 36373 | |
| 36292 | 36374 | var sema: Sema = .{ |
| 36293 | 36375 | .mod = mod, |
| 36294 | 36376 | .gpa = gpa, |
| ... | ... | @@ -36302,6 +36384,7 @@ fn semaStructFields( |
| 36302 | 36384 | .fn_ret_ty_ies = null, |
| 36303 | 36385 | .owner_func_index = .none, |
| 36304 | 36386 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 36387 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36305 | 36388 | }; |
| 36306 | 36389 | defer sema.deinit(); |
| 36307 | 36390 | |
| ... | ... | @@ -36543,6 +36626,9 @@ fn semaStructFieldInits( |
| 36543 | 36626 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); |
| 36544 | 36627 | defer comptime_mutable_decls.deinit(); |
| 36545 | 36628 | |
| 36629 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 36630 | defer comptime_err_ret_trace.deinit(); |
| 36631 | |
| 36546 | 36632 | var sema: Sema = .{ |
| 36547 | 36633 | .mod = mod, |
| 36548 | 36634 | .gpa = gpa, |
| ... | ... | @@ -36556,6 +36642,7 @@ fn semaStructFieldInits( |
| 36556 | 36642 | .fn_ret_ty_ies = null, |
| 36557 | 36643 | .owner_func_index = .none, |
| 36558 | 36644 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 36645 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36559 | 36646 | }; |
| 36560 | 36647 | defer sema.deinit(); |
| 36561 | 36648 | |
| ... | ... | @@ -36727,6 +36814,9 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36727 | 36814 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); |
| 36728 | 36815 | defer comptime_mutable_decls.deinit(); |
| 36729 | 36816 | |
| 36817 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 36818 | defer comptime_err_ret_trace.deinit(); |
| 36819 | |
| 36730 | 36820 | var sema: Sema = .{ |
| 36731 | 36821 | .mod = mod, |
| 36732 | 36822 | .gpa = gpa, |
| ... | ... | @@ -36740,6 +36830,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36740 | 36830 | .fn_ret_ty_ies = null, |
| 36741 | 36831 | .owner_func_index = .none, |
| 36742 | 36832 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 36833 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36743 | 36834 | }; |
| 36744 | 36835 | defer sema.deinit(); |
| 36745 | 36836 | |