| ... | @@ -405,7 +405,9 @@ pub const Block = struct { | ... | @@ -405,7 +405,9 @@ pub const Block = struct { |
| 405 | /// It is shared among all the blocks in an inline or comptime called | 405 | /// It is shared among all the blocks in an inline or comptime called |
| 406 | /// function. | 406 | /// function. |
| 407 | pub const Inlining = struct { | 407 | pub const Inlining = struct { |
| 408 | /// Might be `none`. | 408 | call_block: *Block, |
| | 409 | call_src: LazySrcLoc, |
| | 410 | has_comptime_args: bool, |
| 409 | func: InternPool.Index, | 411 | func: InternPool.Index, |
| 410 | comptime_result: Air.Inst.Ref, | 412 | comptime_result: Air.Inst.Ref, |
| 411 | merges: Merges, | 413 | merges: Merges, |
| ... | @@ -2390,7 +2392,6 @@ pub fn fail( | ... | @@ -2390,7 +2392,6 @@ pub fn fail( |
| 2390 | } | 2392 | } |
| 2391 | | 2393 | |
| 2392 | fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) CompileError { | 2394 | fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) CompileError { |
| 2393 | _ = block; | | |
| 2394 | @setCold(true); | 2395 | @setCold(true); |
| 2395 | const gpa = sema.gpa; | 2396 | const gpa = sema.gpa; |
| 2396 | const mod = sema.mod; | 2397 | const mod = sema.mod; |
| ... | @@ -2414,6 +2415,16 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) | ... | @@ -2414,6 +2415,16 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) |
| 2414 | try mod.failed_decls.ensureUnusedCapacity(gpa, 1); | 2415 | try mod.failed_decls.ensureUnusedCapacity(gpa, 1); |
| 2415 | try mod.failed_files.ensureUnusedCapacity(gpa, 1); | 2416 | try mod.failed_files.ensureUnusedCapacity(gpa, 1); |
| 2416 | | 2417 | |
| | 2418 | var func_index: InternPool.Index = .none; |
| | 2419 | if (block) |start_block| { |
| | 2420 | var block_it = start_block; |
| | 2421 | while (block_it.inlining) |inlining| { |
| | 2422 | func_index = inlining.func; |
| | 2423 | block_it = inlining.call_block; |
| | 2424 | try sema.errNote(block_it, inlining.call_src, err_msg, "called from here", .{}); |
| | 2425 | } |
| | 2426 | } |
| | 2427 | |
| 2417 | const max_references = blk: { | 2428 | const max_references = blk: { |
| 2418 | if (mod.comp.reference_trace) |num| break :blk num; | 2429 | if (mod.comp.reference_trace) |num| break :blk num; |
| 2419 | // Do not add multiple traces without explicit request. | 2430 | // Do not add multiple traces without explicit request. |
| ... | @@ -7268,7 +7279,10 @@ fn analyzeCall( | ... | @@ -7268,7 +7279,10 @@ fn analyzeCall( |
| 7268 | // This one is shared among sub-blocks within the same callee, but not | 7279 | // This one is shared among sub-blocks within the same callee, but not |
| 7269 | // shared among the entire inline/comptime call stack. | 7280 | // shared among the entire inline/comptime call stack. |
| 7270 | var inlining: Block.Inlining = .{ | 7281 | var inlining: Block.Inlining = .{ |
| 7271 | .func = .none, | 7282 | .call_block = block, |
| | 7283 | .call_src = call_src, |
| | 7284 | .has_comptime_args = false, |
| | 7285 | .func = module_fn_index, |
| 7272 | .comptime_result = undefined, | 7286 | .comptime_result = undefined, |
| 7273 | .merges = .{ | 7287 | .merges = .{ |
| 7274 | .src_locs = .{}, | 7288 | .src_locs = .{}, |
| ... | @@ -7352,7 +7366,6 @@ fn analyzeCall( | ... | @@ -7352,7 +7366,6 @@ fn analyzeCall( |
| 7352 | const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst); | 7366 | const fn_info = ics.callee().code.getFnInfo(module_fn.zir_body_inst); |
| 7353 | try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); | 7367 | try ics.callee().inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body); |
| 7354 | | 7368 | |
| 7355 | var has_comptime_args = false; | | |
| 7356 | var arg_i: u32 = 0; | 7369 | var arg_i: u32 = 0; |
| 7357 | for (fn_info.param_body) |inst| { | 7370 | for (fn_info.param_body) |inst| { |
| 7358 | const opt_noreturn_ref = try analyzeInlineCallArg( | 7371 | const opt_noreturn_ref = try analyzeInlineCallArg( |
| ... | @@ -7368,7 +7381,6 @@ fn analyzeCall( | ... | @@ -7368,7 +7381,6 @@ fn analyzeCall( |
| 7368 | memoized_arg_values, | 7381 | memoized_arg_values, |
| 7369 | func_ty_info, | 7382 | func_ty_info, |
| 7370 | func, | 7383 | func, |
| 7371 | &has_comptime_args, | | |
| 7372 | ); | 7384 | ); |
| 7373 | if (opt_noreturn_ref) |ref| { | 7385 | if (opt_noreturn_ref) |ref| { |
| 7374 | // Analyzing this argument gave a ref of a noreturn type. Terminate argument analysis here. | 7386 | // Analyzing this argument gave a ref of a noreturn type. Terminate argument analysis here. |
| ... | @@ -7380,19 +7392,18 @@ fn analyzeCall( | ... | @@ -7380,19 +7392,18 @@ fn analyzeCall( |
| 7380 | // can just use `sema` directly. | 7392 | // can just use `sema` directly. |
| 7381 | _ = ics.callee(); | 7393 | _ = ics.callee(); |
| 7382 | | 7394 | |
| 7383 | if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure) | 7395 | if (!inlining.has_comptime_args) { |
| 7384 | return error.AnalysisFail; | 7396 | if (module_fn.analysis(ip).state == .sema_failure) |
| | 7397 | return error.AnalysisFail; |
| 7385 | | 7398 | |
| 7386 | const recursive_msg = "inline call is recursive"; | 7399 | var block_it = block; |
| 7387 | var head = if (!has_comptime_args) block else null; | 7400 | while (block_it.inlining) |parent_inlining| { |
| 7388 | while (head) |some| { | 7401 | if (!parent_inlining.has_comptime_args and parent_inlining.func == module_fn_index) { |
| 7389 | const parent_inlining = some.inlining orelse break; | 7402 | return sema.fail(block, call_src, "inline call is recursive", .{}); |
| 7390 | if (parent_inlining.func == module_fn_index) { | 7403 | } |
| 7391 | return sema.fail(block, call_src, recursive_msg, .{}); | 7404 | block_it = parent_inlining.call_block; |
| 7392 | } | 7405 | } |
| 7393 | head = some.parent; | | |
| 7394 | } | 7406 | } |
| 7395 | if (!has_comptime_args) inlining.func = module_fn_index; | | |
| 7396 | | 7407 | |
| 7397 | // In case it is a generic function with an expression for the return type that depends | 7408 | // In case it is a generic function with an expression for the return type that depends |
| 7398 | // on parameters, we must now do the same for the return type as we just did with | 7409 | // on parameters, we must now do the same for the return type as we just did with |
| ... | @@ -7462,12 +7473,6 @@ fn analyzeCall( | ... | @@ -7462,12 +7473,6 @@ fn analyzeCall( |
| 7462 | const result = result: { | 7473 | const result = result: { |
| 7463 | sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { | 7474 | sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) { |
| 7464 | error.ComptimeReturn => break :result inlining.comptime_result, | 7475 | error.ComptimeReturn => break :result inlining.comptime_result, |
| 7465 | error.AnalysisFail => { | | |
| 7466 | const err_msg = sema.err orelse return err; | | |
| 7467 | if (mem.eql(u8, err_msg.msg, recursive_msg)) return err; | | |
| 7468 | try sema.errNote(block, call_src, err_msg, "called from here", .{}); | | |
| 7469 | return err; | | |
| 7470 | }, | | |
| 7471 | else => |e| return e, | 7476 | else => |e| return e, |
| 7472 | }; | 7477 | }; |
| 7473 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); | 7478 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); |
| ... | @@ -7632,13 +7637,12 @@ fn analyzeInlineCallArg( | ... | @@ -7632,13 +7637,12 @@ fn analyzeInlineCallArg( |
| 7632 | memoized_arg_values: []InternPool.Index, | 7637 | memoized_arg_values: []InternPool.Index, |
| 7633 | func_ty_info: InternPool.Key.FuncType, | 7638 | func_ty_info: InternPool.Key.FuncType, |
| 7634 | func_inst: Air.Inst.Ref, | 7639 | func_inst: Air.Inst.Ref, |
| 7635 | has_comptime_args: *bool, | | |
| 7636 | ) !?Air.Inst.Ref { | 7640 | ) !?Air.Inst.Ref { |
| 7637 | const mod = ics.sema.mod; | 7641 | const mod = ics.sema.mod; |
| 7638 | const ip = &mod.intern_pool; | 7642 | const ip = &mod.intern_pool; |
| 7639 | const zir_tags = ics.callee().code.instructions.items(.tag); | 7643 | const zir_tags = ics.callee().code.instructions.items(.tag); |
| 7640 | switch (zir_tags[inst]) { | 7644 | switch (zir_tags[inst]) { |
| 7641 | .param_comptime, .param_anytype_comptime => has_comptime_args.* = true, | 7645 | .param_comptime, .param_anytype_comptime => param_block.inlining.?.has_comptime_args = true, |
| 7642 | else => {}, | 7646 | else => {}, |
| 7643 | } | 7647 | } |
| 7644 | switch (zir_tags[inst]) { | 7648 | switch (zir_tags[inst]) { |
| ... | @@ -7698,7 +7702,7 @@ fn analyzeInlineCallArg( | ... | @@ -7698,7 +7702,7 @@ fn analyzeInlineCallArg( |
| 7698 | } | 7702 | } |
| 7699 | | 7703 | |
| 7700 | if (try ics.caller().resolveMaybeUndefVal(casted_arg)) |_| { | 7704 | if (try ics.caller().resolveMaybeUndefVal(casted_arg)) |_| { |
| 7701 | has_comptime_args.* = true; | 7705 | param_block.inlining.?.has_comptime_args = true; |
| 7702 | } | 7706 | } |
| 7703 | | 7707 | |
| 7704 | arg_i.* += 1; | 7708 | arg_i.* += 1; |
| ... | @@ -7742,7 +7746,7 @@ fn analyzeInlineCallArg( | ... | @@ -7742,7 +7746,7 @@ fn analyzeInlineCallArg( |
| 7742 | } | 7746 | } |
| 7743 | | 7747 | |
| 7744 | if (try ics.caller().resolveMaybeUndefVal(uncasted_arg)) |_| { | 7748 | if (try ics.caller().resolveMaybeUndefVal(uncasted_arg)) |_| { |
| 7745 | has_comptime_args.* = true; | 7749 | param_block.inlining.?.has_comptime_args = true; |
| 7746 | } | 7750 | } |
| 7747 | | 7751 | |
| 7748 | arg_i.* += 1; | 7752 | arg_i.* += 1; |