authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-05-16 22:42:07+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-05-16 22:42:07+01:00
log9064907b34128d66ffae8d15e075eddab7af0153
tree00cd0fb6c0a19ce56074b14947f36ef6f4ff035d
parent9279ff888bd1b00d4369b4d234e31a161f02a247
parent46d7e808dcef3c9f9200d6cc1ed4e3a787ba054d
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #23907 from mlugg/ref-trace

compiler: reference trace fixes

29 files changed, 253 insertions(+), 150 deletions(-)

lib/compiler/build_runner.zig+2-6
...@@ -750,7 +750,7 @@ fn runStepNames(...@@ -750,7 +750,7 @@ fn runStepNames(
750 if (run.prominent_compile_errors and total_compile_errors > 0) {750 if (run.prominent_compile_errors and total_compile_errors > 0) {
751 for (step_stack.keys()) |s| {751 for (step_stack.keys()) |s| {
752 if (s.result_error_bundle.errorMessageCount() > 0) {752 if (s.result_error_bundle.errorMessageCount() > 0) {
753 s.result_error_bundle.renderToStdErr(.{ .ttyconf = ttyconf, .include_reference_trace = (b.reference_trace orelse 0) > 0 });753 s.result_error_bundle.renderToStdErr(.{ .ttyconf = ttyconf });
754 }754 }
755 }755 }
756756
...@@ -1129,11 +1129,7 @@ fn workerMakeOneStep(...@@ -1129,11 +1129,7 @@ fn workerMakeOneStep(
1129 defer std.debug.unlockStdErr();1129 defer std.debug.unlockStdErr();
11301130
1131 const gpa = b.allocator;1131 const gpa = b.allocator;
1132 const options: std.zig.ErrorBundle.RenderOptions = .{1132 printErrorMessages(gpa, s, .{ .ttyconf = run.ttyconf }, run.stderr, run.prominent_compile_errors) catch {};
1133 .ttyconf = run.ttyconf,
1134 .include_reference_trace = (b.reference_trace orelse 0) > 0,
1135 };
1136 printErrorMessages(gpa, s, options, run.stderr, run.prominent_compile_errors) catch {};
1137 }1133 }
11381134
1139 handle_result: {1135 handle_result: {
src/Compilation.zig+65-30
...@@ -3328,7 +3328,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3328,7 +3328,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3328 if (comp.zcu) |zcu| zcu_errors: {3328 if (comp.zcu) |zcu| zcu_errors: {
3329 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {3329 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {
3330 if (error_msg) |msg| {3330 if (error_msg) |msg| {
3331 try addModuleErrorMsg(zcu, &bundle, msg.*);3331 try addModuleErrorMsg(zcu, &bundle, msg.*, false);
3332 } else {3332 } else {
3333 // Must be ZIR or Zoir errors. Note that this may include AST errors.3333 // Must be ZIR or Zoir errors. Note that this may include AST errors.
3334 _ = try file.getTree(gpa); // Tree must be loaded.3334 _ = try file.getTree(gpa); // Tree must be loaded.
...@@ -3378,6 +3378,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3378,6 +3378,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3378 break :s entries.slice();3378 break :s entries.slice();
3379 };3379 };
3380 defer sorted_failed_analysis.deinit(gpa);3380 defer sorted_failed_analysis.deinit(gpa);
3381 var added_any_analysis_error = false;
3381 for (sorted_failed_analysis.items(.key), sorted_failed_analysis.items(.value)) |anal_unit, error_msg| {3382 for (sorted_failed_analysis.items(.key), sorted_failed_analysis.items(.value)) |anal_unit, error_msg| {
3382 if (comp.incremental) {3383 if (comp.incremental) {
3383 const refs = try zcu.resolveReferences();3384 const refs = try zcu.resolveReferences();
...@@ -3389,7 +3390,9 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3389,7 +3390,9 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3389 zcu.fmtAnalUnit(anal_unit),3390 zcu.fmtAnalUnit(anal_unit),
3390 });3391 });
33913392
3392 try addModuleErrorMsg(zcu, &bundle, error_msg.*);3393 try addModuleErrorMsg(zcu, &bundle, error_msg.*, added_any_analysis_error);
3394 added_any_analysis_error = true;
3395
3393 if (zcu.cimport_errors.get(anal_unit)) |errors| {3396 if (zcu.cimport_errors.get(anal_unit)) |errors| {
3394 for (errors.getMessages()) |err_msg_index| {3397 for (errors.getMessages()) |err_msg_index| {
3395 const err_msg = errors.getErrorMessage(err_msg_index);3398 const err_msg = errors.getErrorMessage(err_msg_index);
...@@ -3412,13 +3415,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3412,13 +3415,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3412 }3415 }
3413 }3416 }
3414 for (zcu.failed_codegen.values()) |error_msg| {3417 for (zcu.failed_codegen.values()) |error_msg| {
3415 try addModuleErrorMsg(zcu, &bundle, error_msg.*);3418 try addModuleErrorMsg(zcu, &bundle, error_msg.*, false);
3416 }3419 }
3417 for (zcu.failed_types.values()) |error_msg| {3420 for (zcu.failed_types.values()) |error_msg| {
3418 try addModuleErrorMsg(zcu, &bundle, error_msg.*);3421 try addModuleErrorMsg(zcu, &bundle, error_msg.*, false);
3419 }3422 }
3420 for (zcu.failed_exports.values()) |value| {3423 for (zcu.failed_exports.values()) |value| {
3421 try addModuleErrorMsg(zcu, &bundle, value.*);3424 try addModuleErrorMsg(zcu, &bundle, value.*, false);
3422 }3425 }
34233426
3424 const actual_error_count = zcu.intern_pool.global_error_set.getNamesFromMainThread().len;3427 const actual_error_count = zcu.intern_pool.global_error_set.getNamesFromMainThread().len;
...@@ -3527,7 +3530,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3527,7 +3530,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3527 // We don't actually include the error here if `!include_compile_log_sources`.3530 // We don't actually include the error here if `!include_compile_log_sources`.
3528 // The sorting above was still necessary, though, to get `log_text` in the right order.3531 // The sorting above was still necessary, though, to get `log_text` in the right order.
3529 if (include_compile_log_sources) {3532 if (include_compile_log_sources) {
3530 try addModuleErrorMsg(zcu, &bundle, messages.items[0]);3533 try addModuleErrorMsg(zcu, &bundle, messages.items[0], false);
3531 }3534 }
35323535
3533 break :compile_log_text try log_text.toOwnedSlice(gpa);3536 break :compile_log_text try log_text.toOwnedSlice(gpa);
...@@ -3631,10 +3634,14 @@ pub const ErrorNoteHashContext = struct {...@@ -3631,10 +3634,14 @@ pub const ErrorNoteHashContext = struct {
3631 }3634 }
3632};3635};
36333636
3637const default_reference_trace_len = 2;
3634pub fn addModuleErrorMsg(3638pub fn addModuleErrorMsg(
3635 zcu: *Zcu,3639 zcu: *Zcu,
3636 eb: *ErrorBundle.Wip,3640 eb: *ErrorBundle.Wip,
3637 module_err_msg: Zcu.ErrorMsg,3641 module_err_msg: Zcu.ErrorMsg,
3642 /// If `-freference-trace` is not specified, we only want to show the one reference trace.
3643 /// So, this is whether we have already emitted an error with a reference trace.
3644 already_added_error: bool,
3638) !void {3645) !void {
3639 const gpa = eb.gpa;3646 const gpa = eb.gpa;
3640 const ip = &zcu.intern_pool;3647 const ip = &zcu.intern_pool;
...@@ -3657,45 +3664,44 @@ pub fn addModuleErrorMsg(...@@ -3657,45 +3664,44 @@ pub fn addModuleErrorMsg(
3657 var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .empty;3664 var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .empty;
3658 defer ref_traces.deinit(gpa);3665 defer ref_traces.deinit(gpa);
36593666
3660 if (module_err_msg.reference_trace_root.unwrap()) |rt_root| {3667 rt: {
3668 const rt_root = module_err_msg.reference_trace_root.unwrap() orelse break :rt;
3669 const max_references = zcu.comp.reference_trace orelse refs: {
3670 if (already_added_error) break :rt;
3671 break :refs default_reference_trace_len;
3672 };
3673
3661 const all_references = try zcu.resolveReferences();3674 const all_references = try zcu.resolveReferences();
36623675
3663 var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty;3676 var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty;
3664 defer seen.deinit(gpa);3677 defer seen.deinit(gpa);
36653678
3666 const max_references = zcu.comp.reference_trace orelse Sema.default_reference_trace_len;
3667
3668 var referenced_by = rt_root;3679 var referenced_by = rt_root;
3669 while (all_references.get(referenced_by)) |maybe_ref| {3680 while (all_references.get(referenced_by)) |maybe_ref| {
3670 const ref = maybe_ref orelse break;3681 const ref = maybe_ref orelse break;
3671 const gop = try seen.getOrPut(gpa, ref.referencer);3682 const gop = try seen.getOrPut(gpa, ref.referencer);
3672 if (gop.found_existing) break;3683 if (gop.found_existing) break;
3673 if (ref_traces.items.len < max_references) skip: {3684 if (ref_traces.items.len < max_references) {
3674 const src = ref.src.upgrade(zcu);3685 var last_call_src = ref.src;
3675 const source = try src.file_scope.getSource(gpa);3686 var opt_inline_frame = ref.inline_frame;
3676 const span = try src.span(gpa);3687 while (opt_inline_frame.unwrap()) |inline_frame| {
3677 const loc = std.zig.findLineColumn(source.bytes, span.main);3688 const f = inline_frame.ptr(zcu).*;
3678 const rt_file_path = try src.file_scope.fullPath(gpa);3689 const func_nav = ip.indexToKey(f.callee).func.owner_nav;
3679 defer gpa.free(rt_file_path);3690 const func_name = ip.getNav(func_nav).name.toSlice(ip);
3680 const name = switch (ref.referencer.unwrap()) {3691 try addReferenceTraceFrame(zcu, eb, &ref_traces, func_name, last_call_src, true);
3692 last_call_src = f.call_src;
3693 opt_inline_frame = f.parent;
3694 }
3695 const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) {
3681 .@"comptime" => "comptime",3696 .@"comptime" => "comptime",
3682 .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),3697 .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
3683 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),3698 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
3684 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),3699 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
3685 .memoized_state => break :skip,3700 .memoized_state => null,
3686 };3701 };
3687 try ref_traces.append(gpa, .{3702 if (root_name) |n| {
3688 .decl_name = try eb.addString(name),3703 try addReferenceTraceFrame(zcu, eb, &ref_traces, n, last_call_src, false);
3689 .src_loc = try eb.addSourceLocation(.{3704 }
3690 .src_path = try eb.addString(rt_file_path),
3691 .span_start = span.start,
3692 .span_main = span.main,
3693 .span_end = span.end,
3694 .line = @intCast(loc.line),
3695 .column = @intCast(loc.column),
3696 .source_line = 0,
3697 }),
3698 });
3699 }3705 }
3700 referenced_by = ref.referencer;3706 referenced_by = ref.referencer;
3701 }3707 }
...@@ -3775,6 +3781,35 @@ pub fn addModuleErrorMsg(...@@ -3775,6 +3781,35 @@ pub fn addModuleErrorMsg(
3775 }3781 }
3776}3782}
37773783
3784fn addReferenceTraceFrame(
3785 zcu: *Zcu,
3786 eb: *ErrorBundle.Wip,
3787 ref_traces: *std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace),
3788 name: []const u8,
3789 lazy_src: Zcu.LazySrcLoc,
3790 inlined: bool,
3791) !void {
3792 const gpa = zcu.gpa;
3793 const src = lazy_src.upgrade(zcu);
3794 const source = try src.file_scope.getSource(gpa);
3795 const span = try src.span(gpa);
3796 const loc = std.zig.findLineColumn(source.bytes, span.main);
3797 const rt_file_path = try src.file_scope.fullPath(gpa);
3798 defer gpa.free(rt_file_path);
3799 try ref_traces.append(gpa, .{
3800 .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }),
3801 .src_loc = try eb.addSourceLocation(.{
3802 .src_path = try eb.addString(rt_file_path),
3803 .span_start = span.start,
3804 .span_main = span.main,
3805 .span_end = span.end,
3806 .line = @intCast(loc.line),
3807 .column = @intCast(loc.column),
3808 .source_line = 0,
3809 }),
3810 });
3811}
3812
3778pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void {3813pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void {
3779 const gpa = eb.gpa;3814 const gpa = eb.gpa;
3780 const src_path = try file.fullPath(gpa);3815 const src_path = try file.fullPath(gpa);
src/Sema.zig+77-51
...@@ -191,7 +191,6 @@ const LowerZon = @import("Sema/LowerZon.zig");...@@ -191,7 +191,6 @@ const LowerZon = @import("Sema/LowerZon.zig");
191const arith = @import("Sema/arith.zig");191const arith = @import("Sema/arith.zig");
192192
193pub const default_branch_quota = 1000;193pub const default_branch_quota = 1000;
194pub const default_reference_trace_len = 2;
195194
196pub const InferredErrorSet = struct {195pub const InferredErrorSet = struct {
197 /// The function body from which this error set originates.196 /// The function body from which this error set originates.
...@@ -445,10 +444,31 @@ pub const Block = struct {...@@ -445,10 +444,31 @@ pub const Block = struct {
445 pub const Inlining = struct {444 pub const Inlining = struct {
446 call_block: *Block,445 call_block: *Block,
447 call_src: LazySrcLoc,446 call_src: LazySrcLoc,
448 has_comptime_args: bool,
449 func: InternPool.Index,447 func: InternPool.Index,
448
449 /// Populated lazily by `refFrame`.
450 ref_frame: Zcu.InlineReferenceFrame.Index.Optional = .none,
451
452 /// If `true`, the following fields are `undefined`. This doesn't represent a true inline
453 /// call, but rather a generic call analyzing the instantiation's generic type bodies.
454 is_generic_instantiation: bool,
455
456 has_comptime_args: bool,
450 comptime_result: Air.Inst.Ref,457 comptime_result: Air.Inst.Ref,
451 merges: Merges,458 merges: Merges,
459
460 fn refFrame(inlining: *Inlining, zcu: *Zcu) Allocator.Error!Zcu.InlineReferenceFrame.Index {
461 if (inlining.ref_frame == .none) {
462 inlining.ref_frame = (try zcu.addInlineReferenceFrame(.{
463 .callee = inlining.func,
464 .call_src = inlining.call_src,
465 .parent = if (inlining.call_block.inlining) |parent_inlining| p: {
466 break :p (try parent_inlining.refFrame(zcu)).toOptional();
467 } else .none,
468 })).toOptional();
469 }
470 return inlining.ref_frame.unwrap().?;
471 }
452 };472 };
453473
454 pub const Merges = struct {474 pub const Merges = struct {
...@@ -2580,7 +2600,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg...@@ -2580,7 +2600,7 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
2580 if (build_options.enable_debug_extensions and zcu.comp.debug_compile_errors) {2600 if (build_options.enable_debug_extensions and zcu.comp.debug_compile_errors) {
2581 var wip_errors: std.zig.ErrorBundle.Wip = undefined;2601 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
2582 wip_errors.init(gpa) catch @panic("out of memory");2602 wip_errors.init(gpa) catch @panic("out of memory");
2583 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*) catch @panic("out of memory");2603 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory");
2584 std.debug.print("compile error during Sema:\n", .{});2604 std.debug.print("compile error during Sema:\n", .{});
2585 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");2605 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory");
2586 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });2606 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });
...@@ -2590,20 +2610,17 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg...@@ -2590,20 +2610,17 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
2590 if (block) |start_block| {2610 if (block) |start_block| {
2591 var block_it = start_block;2611 var block_it = start_block;
2592 while (block_it.inlining) |inlining| {2612 while (block_it.inlining) |inlining| {
2593 try sema.errNote(2613 const note_str = note: {
2594 inlining.call_src,2614 if (inlining.is_generic_instantiation) break :note "generic function instantiated here";
2595 err_msg,2615 if (inlining.call_block.isComptime()) break :note "called at comptime here";
2596 "called from here",2616 break :note "called inline here";
2597 .{},2617 };
2598 );2618 try sema.errNote(inlining.call_src, err_msg, "{s}", .{note_str});
2599 block_it = inlining.call_block;2619 block_it = inlining.call_block;
2600 }2620 }
2601 }2621 }
26022622
2603 const use_ref_trace = if (zcu.comp.reference_trace) |n| n > 0 else zcu.failed_analysis.count() == 0;2623 err_msg.reference_trace_root = sema.owner.toOptional();
2604 if (use_ref_trace) {
2605 err_msg.reference_trace_root = sema.owner.toOptional();
2606 }
26072624
2608 const gop = try zcu.failed_analysis.getOrPut(gpa, sema.owner);2625 const gop = try zcu.failed_analysis.getOrPut(gpa, sema.owner);
2609 if (gop.found_existing) {2626 if (gop.found_existing) {
...@@ -4291,7 +4308,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4291,7 +4308,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4291 if (zcu.intern_pool.isFuncBody(val)) {4308 if (zcu.intern_pool.isFuncBody(val)) {
4292 const ty = Type.fromInterned(zcu.intern_pool.typeOf(val));4309 const ty = Type.fromInterned(zcu.intern_pool.typeOf(val));
4293 if (try ty.fnHasRuntimeBitsSema(pt)) {4310 if (try ty.fnHasRuntimeBitsSema(pt)) {
4294 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = val }));4311 try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = val }));
4295 try zcu.ensureFuncBodyAnalysisQueued(val);4312 try zcu.ensureFuncBodyAnalysisQueued(val);
4296 }4313 }
4297 }4314 }
...@@ -6619,7 +6636,7 @@ pub fn analyzeExport(...@@ -6619,7 +6636,7 @@ pub fn analyzeExport(
6619 if (options.linkage == .internal)6636 if (options.linkage == .internal)
6620 return;6637 return;
66216638
6622 try sema.ensureNavResolved(src, orig_nav_index, .fully);6639 try sema.ensureNavResolved(block, src, orig_nav_index, .fully);
66236640
6624 const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {6641 const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {
6625 .variable => |v| v.owner_nav,6642 .variable => |v| v.owner_nav,
...@@ -6648,7 +6665,7 @@ pub fn analyzeExport(...@@ -6648,7 +6665,7 @@ pub fn analyzeExport(
6648 return sema.fail(block, src, "export target cannot be extern", .{});6665 return sema.fail(block, src, "export target cannot be extern", .{});
6649 }6666 }
66506667
6651 try sema.maybeQueueFuncBodyAnalysis(src, exported_nav_index);6668 try sema.maybeQueueFuncBodyAnalysis(block, src, exported_nav_index);
66526669
6653 try sema.exports.append(gpa, .{6670 try sema.exports.append(gpa, .{
6654 .opts = options,6671 .opts = options,
...@@ -6896,7 +6913,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -6896,7 +6913,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
6896 .no_embedded_nulls,6913 .no_embedded_nulls,
6897 );6914 );
6898 const nav_index = try sema.lookupIdentifier(block, src, decl_name);6915 const nav_index = try sema.lookupIdentifier(block, src, decl_name);
6899 return sema.analyzeNavRef(src, nav_index);6916 return sema.analyzeNavRef(block, src, nav_index);
6900}6917}
69016918
6902fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6919fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -6992,7 +7009,7 @@ fn lookupInNamespace(...@@ -6992,7 +7009,7 @@ fn lookupInNamespace(
6992 }7009 }
69937010
6994 for (usingnamespaces.items) |sub_ns_nav| {7011 for (usingnamespaces.items) |sub_ns_nav| {
6995 try sema.ensureNavResolved(src, sub_ns_nav, .fully);7012 try sema.ensureNavResolved(block, src, sub_ns_nav, .fully);
6996 const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val);7013 const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val);
6997 const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu));7014 const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu));
6998 try checked_namespaces.put(gpa, sub_ns, {});7015 try checked_namespaces.put(gpa, sub_ns, {});
...@@ -7724,10 +7741,11 @@ fn analyzeCall(...@@ -7724,10 +7741,11 @@ fn analyzeCall(
7724 var generic_inlining: Block.Inlining = if (func_ty_info.is_generic) .{7741 var generic_inlining: Block.Inlining = if (func_ty_info.is_generic) .{
7725 .call_block = block,7742 .call_block = block,
7726 .call_src = call_src,7743 .call_src = call_src,
7727 .has_comptime_args = false, // unused by error reporting7744 .func = func_val.?.toIntern(),
7728 .func = .none, // unused by error reporting7745 .is_generic_instantiation = true, // this allows the following fields to be `undefined`
7729 .comptime_result = .none, // unused by error reporting7746 .has_comptime_args = undefined,
7730 .merges = undefined, // unused because we'll never `return`7747 .comptime_result = undefined,
7748 .merges = undefined,
7731 } else undefined;7749 } else undefined;
77327750
7733 // This is the block in which we evaluate generic function components: that is, generic parameter7751 // This is the block in which we evaluate generic function components: that is, generic parameter
...@@ -8003,7 +8021,7 @@ fn analyzeCall(...@@ -8003,7 +8021,7 @@ fn analyzeCall(
8003 ref_func: {8021 ref_func: {
8004 const runtime_func_val = try sema.resolveValue(runtime_func) orelse break :ref_func;8022 const runtime_func_val = try sema.resolveValue(runtime_func) orelse break :ref_func;
8005 if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func;8023 if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func;
8006 try sema.addReferenceEntry(call_src, .wrap(.{ .func = runtime_func_val.toIntern() }));8024 try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = runtime_func_val.toIntern() }));
8007 try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern());8025 try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern());
8008 }8026 }
80098027
...@@ -8205,10 +8223,11 @@ fn analyzeCall(...@@ -8205,10 +8223,11 @@ fn analyzeCall(
8205 var inlining: Block.Inlining = .{8223 var inlining: Block.Inlining = .{
8206 .call_block = block,8224 .call_block = block,
8207 .call_src = call_src,8225 .call_src = call_src,
8226 .func = func_val.?.toIntern(),
8227 .is_generic_instantiation = false,
8208 .has_comptime_args = for (args) |a| {8228 .has_comptime_args = for (args) |a| {
8209 if (try sema.isComptimeKnown(a)) break true;8229 if (try sema.isComptimeKnown(a)) break true;
8210 } else false,8230 } else false,
8211 .func = func_val.?.toIntern(),
8212 .comptime_result = undefined,8231 .comptime_result = undefined,
8213 .merges = .{8232 .merges = .{
8214 .block_inst = block_inst,8233 .block_inst = block_inst,
...@@ -8239,7 +8258,10 @@ fn analyzeCall(...@@ -8239,7 +8258,10 @@ fn analyzeCall(
8239 if (!inlining.has_comptime_args) {8258 if (!inlining.has_comptime_args) {
8240 var block_it = block;8259 var block_it = block;
8241 while (block_it.inlining) |parent_inlining| {8260 while (block_it.inlining) |parent_inlining| {
8242 if (!parent_inlining.has_comptime_args and parent_inlining.func == func_val.?.toIntern()) {8261 if (!parent_inlining.is_generic_instantiation and
8262 !parent_inlining.has_comptime_args and
8263 parent_inlining.func == func_val.?.toIntern())
8264 {
8243 return sema.fail(block, call_src, "inline call is recursive", .{});8265 return sema.fail(block, call_src, "inline call is recursive", .{});
8244 }8266 }
8245 block_it = parent_inlining.call_block;8267 block_it = parent_inlining.call_block;
...@@ -17258,7 +17280,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17258,7 +17280,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17258 .@"comptime" => |index| return Air.internedToRef(index),17280 .@"comptime" => |index| return Air.internedToRef(index),
17259 .runtime => |index| index,17281 .runtime => |index| index,
17260 .nav_val => |nav| return sema.analyzeNavVal(block, src, nav),17282 .nav_val => |nav| return sema.analyzeNavVal(block, src, nav),
17261 .nav_ref => |nav| return sema.analyzeNavRef(src, nav),17283 .nav_ref => |nav| return sema.analyzeNavRef(block, src, nav),
17262 };17284 };
1726317285
17264 // The comptime case is handled already above. Runtime case below.17286 // The comptime case is handled already above. Runtime case below.
...@@ -18411,7 +18433,7 @@ fn typeInfoNamespaceDecls(...@@ -18411,7 +18433,7 @@ fn typeInfoNamespaceDecls(
18411 if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) {18433 if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) {
18412 continue;18434 continue;
18413 }18435 }
18414 try sema.ensureNavResolved(src, nav, .fully);18436 try sema.ensureNavResolved(block, src, nav, .fully);
18415 const namespace_ty = Type.fromInterned(ip.getNav(nav).status.fully_resolved.val);18437 const namespace_ty = Type.fromInterned(ip.getNav(nav).status.fully_resolved.val);
18416 try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces);18438 try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces);
18417 }18439 }
...@@ -19443,6 +19465,7 @@ fn analyzeRet(...@@ -19443,6 +19465,7 @@ fn analyzeRet(
19443 };19465 };
1944419466
19445 if (block.inlining) |inlining| {19467 if (block.inlining) |inlining| {
19468 assert(!inlining.is_generic_instantiation); // can't `return` in a generic param/ret ty expr
19446 if (block.isComptime()) {19469 if (block.isComptime()) {
19447 const ret_val = try sema.resolveConstValue(block, operand_src, operand, null);19470 const ret_val = try sema.resolveConstValue(block, operand_src, operand, null);
19448 inlining.comptime_result = operand;19471 inlining.comptime_result = operand;
...@@ -27936,7 +27959,7 @@ fn namespaceLookupRef(...@@ -27936,7 +27959,7 @@ fn namespaceLookupRef(
27936 decl_name: InternPool.NullTerminatedString,27959 decl_name: InternPool.NullTerminatedString,
27937) CompileError!?Air.Inst.Ref {27960) CompileError!?Air.Inst.Ref {
27938 const nav = try sema.namespaceLookup(block, src, namespace, decl_name) orelse return null;27961 const nav = try sema.namespaceLookup(block, src, namespace, decl_name) orelse return null;
27939 return try sema.analyzeNavRef(src, nav);27962 return try sema.analyzeNavRef(block, src, nav);
27940}27963}
2794127964
27942fn namespaceLookupVal(27965fn namespaceLookupVal(
...@@ -29099,7 +29122,7 @@ fn coerceExtra(...@@ -29099,7 +29122,7 @@ fn coerceExtra(
29099 .@"extern" => |e| e.owner_nav,29122 .@"extern" => |e| e.owner_nav,
29100 else => unreachable,29123 else => unreachable,
29101 };29124 };
29102 const inst_as_ptr = try sema.analyzeNavRef(inst_src, fn_nav);29125 const inst_as_ptr = try sema.analyzeNavRef(block, inst_src, fn_nav);
29103 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);29126 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
29104 }29127 }
2910529128
...@@ -30752,7 +30775,7 @@ fn coerceVarArgParam(...@@ -30752,7 +30775,7 @@ fn coerceVarArgParam(
30752 .@"fn" => fn_ptr: {30775 .@"fn" => fn_ptr: {
30753 const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);30776 const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
30754 const fn_nav = zcu.funcInfo(fn_val.toIntern()).owner_nav;30777 const fn_nav = zcu.funcInfo(fn_val.toIntern()).owner_nav;
30755 break :fn_ptr try sema.analyzeNavRef(inst_src, fn_nav);30778 break :fn_ptr try sema.analyzeNavRef(block, inst_src, fn_nav);
30756 },30779 },
30757 .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),30780 .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
30758 .float => float: {30781 .float => float: {
...@@ -31762,12 +31785,13 @@ fn analyzeNavVal(...@@ -31762,12 +31785,13 @@ fn analyzeNavVal(
31762 src: LazySrcLoc,31785 src: LazySrcLoc,
31763 nav_index: InternPool.Nav.Index,31786 nav_index: InternPool.Nav.Index,
31764) CompileError!Air.Inst.Ref {31787) CompileError!Air.Inst.Ref {
31765 const ref = try sema.analyzeNavRefInner(src, nav_index, false);31788 const ref = try sema.analyzeNavRefInner(block, src, nav_index, false);
31766 return sema.analyzeLoad(block, src, ref, src);31789 return sema.analyzeLoad(block, src, ref, src);
31767}31790}
3176831791
31769fn addReferenceEntry(31792fn addReferenceEntry(
31770 sema: *Sema,31793 sema: *Sema,
31794 opt_block: ?*Block,
31771 src: LazySrcLoc,31795 src: LazySrcLoc,
31772 referenced_unit: AnalUnit,31796 referenced_unit: AnalUnit,
31773) !void {31797) !void {
...@@ -31775,10 +31799,12 @@ fn addReferenceEntry(...@@ -31775,10 +31799,12 @@ fn addReferenceEntry(
31775 if (!zcu.comp.incremental and zcu.comp.reference_trace == 0) return;31799 if (!zcu.comp.incremental and zcu.comp.reference_trace == 0) return;
31776 const gop = try sema.references.getOrPut(sema.gpa, referenced_unit);31800 const gop = try sema.references.getOrPut(sema.gpa, referenced_unit);
31777 if (gop.found_existing) return;31801 if (gop.found_existing) return;
31778 // TODO: we need to figure out how to model inline calls here.31802 try zcu.addUnitReference(sema.owner, referenced_unit, src, inline_frame: {
31779 // They aren't references in the analysis sense, but ought to show up in the reference trace!31803 const block = opt_block orelse break :inline_frame .none;
31780 // Would representing inline calls in the reference table cause excessive memory usage?31804 const inlining = block.inlining orelse break :inline_frame .none;
31781 try zcu.addUnitReference(sema.owner, referenced_unit, src);31805 const frame = try inlining.refFrame(zcu);
31806 break :inline_frame frame.toOptional();
31807 });
31782}31808}
3178331809
31784pub fn addTypeReferenceEntry(31810pub fn addTypeReferenceEntry(
...@@ -31797,7 +31823,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M...@@ -31797,7 +31823,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
31797 const pt = sema.pt;31823 const pt = sema.pt;
3179831824
31799 const unit: AnalUnit = .wrap(.{ .memoized_state = stage });31825 const unit: AnalUnit = .wrap(.{ .memoized_state = stage });
31800 try sema.addReferenceEntry(src, unit);31826 try sema.addReferenceEntry(null, src, unit);
31801 try sema.declareDependency(.{ .memoized_state = stage });31827 try sema.declareDependency(.{ .memoized_state = stage });
3180231828
31803 if (pt.zcu.analysis_in_progress.contains(unit)) {31829 if (pt.zcu.analysis_in_progress.contains(unit)) {
...@@ -31806,7 +31832,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M...@@ -31806,7 +31832,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
31806 try pt.ensureMemoizedStateUpToDate(stage);31832 try pt.ensureMemoizedStateUpToDate(stage);
31807}31833}
3180831834
31809pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {31835pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
31810 const pt = sema.pt;31836 const pt = sema.pt;
31811 const zcu = pt.zcu;31837 const zcu = pt.zcu;
31812 const ip = &zcu.intern_pool;31838 const ip = &zcu.intern_pool;
...@@ -31829,7 +31855,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav...@@ -31829,7 +31855,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
31829 .type => .{ .nav_ty = nav_index },31855 .type => .{ .nav_ty = nav_index },
31830 .fully => .{ .nav_val = nav_index },31856 .fully => .{ .nav_val = nav_index },
31831 });31857 });
31832 try sema.addReferenceEntry(src, anal_unit);31858 try sema.addReferenceEntry(block, src, anal_unit);
3183331859
31834 if (zcu.analysis_in_progress.contains(anal_unit)) {31860 if (zcu.analysis_in_progress.contains(anal_unit)) {
31835 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{31861 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
...@@ -31859,25 +31885,25 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {...@@ -31859,25 +31885,25 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
31859 } }));31885 } }));
31860}31886}
3186131887
31862fn analyzeNavRef(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!Air.Inst.Ref {31888fn analyzeNavRef(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!Air.Inst.Ref {
31863 return sema.analyzeNavRefInner(src, nav_index, true);31889 return sema.analyzeNavRefInner(block, src, nav_index, true);
31864}31890}
3186531891
31866/// Analyze a reference to the `Nav` at the given index. Ensures the underlying `Nav` is analyzed.31892/// Analyze a reference to the `Nav` at the given index. Ensures the underlying `Nav` is analyzed.
31867/// If this pointer will be used directly, `is_ref` must be `true`.31893/// If this pointer will be used directly, `is_ref` must be `true`.
31868/// If this pointer will be immediately loaded (i.e. a `decl_val` instruction), `is_ref` must be `false`.31894/// If this pointer will be immediately loaded (i.e. a `decl_val` instruction), `is_ref` must be `false`.
31869fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, is_ref: bool) CompileError!Air.Inst.Ref {31895fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, is_ref: bool) CompileError!Air.Inst.Ref {
31870 const pt = sema.pt;31896 const pt = sema.pt;
31871 const zcu = pt.zcu;31897 const zcu = pt.zcu;
31872 const ip = &zcu.intern_pool;31898 const ip = &zcu.intern_pool;
3187331899
31874 try sema.ensureNavResolved(src, orig_nav_index, if (is_ref) .type else .fully);31900 try sema.ensureNavResolved(block, src, orig_nav_index, if (is_ref) .type else .fully);
3187531901
31876 const nav_index = nav: {31902 const nav_index = nav: {
31877 if (ip.getNav(orig_nav_index).isExternOrFn(ip)) {31903 if (ip.getNav(orig_nav_index).isExternOrFn(ip)) {
31878 // Getting a pointer to this `Nav` might mean we actually get a pointer to something else!31904 // Getting a pointer to this `Nav` might mean we actually get a pointer to something else!
31879 // We need to resolve the value to know for sure.31905 // We need to resolve the value to know for sure.
31880 if (is_ref) try sema.ensureNavResolved(src, orig_nav_index, .fully);31906 if (is_ref) try sema.ensureNavResolved(block, src, orig_nav_index, .fully);
31881 switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {31907 switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {
31882 .func => |f| break :nav f.owner_nav,31908 .func => |f| break :nav f.owner_nav,
31883 .@"extern" => |e| break :nav e.owner_nav,31909 .@"extern" => |e| break :nav e.owner_nav,
...@@ -31901,7 +31927,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N...@@ -31901,7 +31927,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N
31901 },31927 },
31902 });31928 });
31903 if (is_ref) {31929 if (is_ref) {
31904 try sema.maybeQueueFuncBodyAnalysis(src, nav_index);31930 try sema.maybeQueueFuncBodyAnalysis(block, src, nav_index);
31905 }31931 }
31906 return Air.internedToRef((try pt.intern(.{ .ptr = .{31932 return Air.internedToRef((try pt.intern(.{ .ptr = .{
31907 .ty = ptr_ty.toIntern(),31933 .ty = ptr_ty.toIntern(),
...@@ -31910,7 +31936,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N...@@ -31910,7 +31936,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N
31910 } })));31936 } })));
31911}31937}
3191231938
31913fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void {31939fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void {
31914 const pt = sema.pt;31940 const pt = sema.pt;
31915 const zcu = pt.zcu;31941 const zcu = pt.zcu;
31916 const ip = &zcu.intern_pool;31942 const ip = &zcu.intern_pool;
...@@ -31918,16 +31944,16 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPoo...@@ -31918,16 +31944,16 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPoo
31918 // To avoid forcing too much resolution, let's first resolve the type, and check if it's a function.31944 // To avoid forcing too much resolution, let's first resolve the type, and check if it's a function.
31919 // If it is, we can resolve the *value*, and queue analysis as needed.31945 // If it is, we can resolve the *value*, and queue analysis as needed.
3192031946
31921 try sema.ensureNavResolved(src, nav_index, .type);31947 try sema.ensureNavResolved(block, src, nav_index, .type);
31922 const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip));31948 const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip));
31923 if (nav_ty.zigTypeTag(zcu) != .@"fn") return;31949 if (nav_ty.zigTypeTag(zcu) != .@"fn") return;
31924 if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return;31950 if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return;
3192531951
31926 try sema.ensureNavResolved(src, nav_index, .fully);31952 try sema.ensureNavResolved(block, src, nav_index, .fully);
31927 const nav_val = zcu.navValue(nav_index);31953 const nav_val = zcu.navValue(nav_index);
31928 if (!ip.isFuncBody(nav_val.toIntern())) return;31954 if (!ip.isFuncBody(nav_val.toIntern())) return;
3192931955
31930 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = nav_val.toIntern() }));31956 try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = nav_val.toIntern() }));
31931 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());31957 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());
31932}31958}
3193331959
...@@ -31943,8 +31969,8 @@ fn analyzeRef(...@@ -31943,8 +31969,8 @@ fn analyzeRef(
3194331969
31944 if (try sema.resolveValue(operand)) |val| {31970 if (try sema.resolveValue(operand)) |val| {
31945 switch (zcu.intern_pool.indexToKey(val.toIntern())) {31971 switch (zcu.intern_pool.indexToKey(val.toIntern())) {
31946 .@"extern" => |e| return sema.analyzeNavRef(src, e.owner_nav),31972 .@"extern" => |e| return sema.analyzeNavRef(block, src, e.owner_nav),
31947 .func => |f| return sema.analyzeNavRef(src, f.owner_nav),31973 .func => |f| return sema.analyzeNavRef(block, src, f.owner_nav),
31948 else => return uavRef(sema, val.toIntern()),31974 else => return uavRef(sema, val.toIntern()),
31949 }31975 }
31950 }31976 }
...@@ -35508,7 +35534,7 @@ fn resolveInferredErrorSet(...@@ -35508,7 +35534,7 @@ fn resolveInferredErrorSet(
35508 }35534 }
35509 // In this case we are dealing with the actual InferredErrorSet object that35535 // In this case we are dealing with the actual InferredErrorSet object that
35510 // corresponds to the function, not one created to track an inline/comptime call.35536 // corresponds to the function, not one created to track an inline/comptime call.
35511 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));35537 try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = func_index }));
35512 try pt.ensureFuncBodyUpToDate(func_index);35538 try pt.ensureFuncBodyUpToDate(func_index);
35513 }35539 }
3551435540
src/Sema/comptime_ptr_access.zig+1-1
...@@ -228,7 +228,7 @@ fn loadComptimePtrInner(...@@ -228,7 +228,7 @@ fn loadComptimePtrInner(
228228
229 const base_val: MutableValue = switch (ptr.base_addr) {229 const base_val: MutableValue = switch (ptr.base_addr) {
230 .nav => |nav| val: {230 .nav => |nav| val: {
231 try sema.ensureNavResolved(src, nav, .fully);231 try sema.ensureNavResolved(block, src, nav, .fully);
232 const val = ip.getNav(nav).status.fully_resolved.val;232 const val = ip.getNav(nav).status.fully_resolved.val;
233 switch (ip.indexToKey(val)) {233 switch (ip.indexToKey(val)) {
234 .variable => return .runtime_load,234 .variable => return .runtime_load,
src/Zcu.zig+78-2
...@@ -215,6 +215,9 @@ all_references: std.ArrayListUnmanaged(Reference) = .empty,...@@ -215,6 +215,9 @@ all_references: std.ArrayListUnmanaged(Reference) = .empty,
215/// Freelist of indices in `all_references`.215/// Freelist of indices in `all_references`.
216free_references: std.ArrayListUnmanaged(u32) = .empty,216free_references: std.ArrayListUnmanaged(u32) = .empty,
217217
218inline_reference_frames: std.ArrayListUnmanaged(InlineReferenceFrame) = .empty,
219free_inline_reference_frames: std.ArrayListUnmanaged(InlineReferenceFrame.Index) = .empty,
220
218/// Key is the `AnalUnit` *performing* the reference. This representation allows221/// Key is the `AnalUnit` *performing* the reference. This representation allows
219/// incremental updates to quickly delete references caused by a specific `AnalUnit`.222/// incremental updates to quickly delete references caused by a specific `AnalUnit`.
220/// Value is index into `all_type_reference` of the first reference triggered by the unit.223/// Value is index into `all_type_reference` of the first reference triggered by the unit.
...@@ -583,6 +586,42 @@ pub const Reference = struct {...@@ -583,6 +586,42 @@ pub const Reference = struct {
583 next: u32,586 next: u32,
584 /// The source location of the reference.587 /// The source location of the reference.
585 src: LazySrcLoc,588 src: LazySrcLoc,
589 /// If not `.none`, this is the index of the `InlineReferenceFrame` which should appear
590 /// between the referencer and `referenced` in the reference trace. These frames represent
591 /// inline calls, which do not create actual references (since they happen in the caller's
592 /// `AnalUnit`), but do show in the reference trace.
593 inline_frame: InlineReferenceFrame.Index.Optional,
594};
595
596pub const InlineReferenceFrame = struct {
597 /// The inline *callee*; that is, the function which was called inline.
598 /// The *caller* is either `parent`, or else the unit causing the original `Reference`.
599 callee: InternPool.Index,
600 /// The source location of the inline call, in the *caller*.
601 call_src: LazySrcLoc,
602 /// If not `.none`, a frame which should appear directly below this one.
603 /// This will be the "parent" inline call; this frame's `callee` is our caller.
604 parent: InlineReferenceFrame.Index.Optional,
605
606 pub const Index = enum(u32) {
607 _,
608 pub fn ptr(idx: Index, zcu: *Zcu) *InlineReferenceFrame {
609 return &zcu.inline_reference_frames.items[@intFromEnum(idx)];
610 }
611 pub fn toOptional(idx: Index) Optional {
612 return @enumFromInt(@intFromEnum(idx));
613 }
614 pub const Optional = enum(u32) {
615 none = std.math.maxInt(u32),
616 _,
617 pub fn unwrap(opt: Optional) ?Index {
618 return switch (opt) {
619 .none => null,
620 _ => @enumFromInt(@intFromEnum(opt)),
621 };
622 }
623 };
624 };
586};625};
587626
588pub const TypeReference = struct {627pub const TypeReference = struct {
...@@ -3440,12 +3479,28 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void {...@@ -3440,12 +3479,28 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void {
3440 var idx = kv.value;3479 var idx = kv.value;
34413480
3442 while (idx != std.math.maxInt(u32)) {3481 while (idx != std.math.maxInt(u32)) {
3482 const ref = zcu.all_references.items[idx];
3443 zcu.free_references.append(gpa, idx) catch {3483 zcu.free_references.append(gpa, idx) catch {
3444 // This space will be reused eventually, so we need not propagate this error.3484 // This space will be reused eventually, so we need not propagate this error.
3445 // Just leak it for now, and let GC reclaim it later on.3485 // Just leak it for now, and let GC reclaim it later on.
3446 break :unit_refs;3486 break :unit_refs;
3447 };3487 };
3448 idx = zcu.all_references.items[idx].next;3488 idx = ref.next;
3489
3490 var opt_inline_frame = ref.inline_frame;
3491 while (opt_inline_frame.unwrap()) |inline_frame| {
3492 // The same inline frame could be used multiple times by one unit. We need to
3493 // detect this case to avoid adding it to `free_inline_reference_frames` more
3494 // than once. We do that by setting `parent` to itself as a marker.
3495 if (inline_frame.ptr(zcu).parent == inline_frame.toOptional()) break;
3496 zcu.free_inline_reference_frames.append(gpa, inline_frame) catch {
3497 // This space will be reused eventually, so we need not propagate this error.
3498 // Just leak it for now, and let GC reclaim it later on.
3499 break :unit_refs;
3500 };
3501 opt_inline_frame = inline_frame.ptr(zcu).parent;
3502 inline_frame.ptr(zcu).parent = inline_frame.toOptional(); // signal to code above
3503 }
3449 }3504 }
3450 }3505 }
34513506
...@@ -3480,7 +3535,22 @@ pub fn deleteUnitCompileLogs(zcu: *Zcu, anal_unit: AnalUnit) void {...@@ -3480,7 +3535,22 @@ pub fn deleteUnitCompileLogs(zcu: *Zcu, anal_unit: AnalUnit) void {
3480 }3535 }
3481}3536}
34823537
3483pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void {3538pub fn addInlineReferenceFrame(zcu: *Zcu, frame: InlineReferenceFrame) Allocator.Error!Zcu.InlineReferenceFrame.Index {
3539 const frame_idx: InlineReferenceFrame.Index = zcu.free_inline_reference_frames.pop() orelse idx: {
3540 _ = try zcu.inline_reference_frames.addOne(zcu.gpa);
3541 break :idx @enumFromInt(zcu.inline_reference_frames.items.len - 1);
3542 };
3543 frame_idx.ptr(zcu).* = frame;
3544 return frame_idx;
3545}
3546
3547pub fn addUnitReference(
3548 zcu: *Zcu,
3549 src_unit: AnalUnit,
3550 referenced_unit: AnalUnit,
3551 ref_src: LazySrcLoc,
3552 inline_frame: InlineReferenceFrame.Index.Optional,
3553) Allocator.Error!void {
3484 const gpa = zcu.gpa;3554 const gpa = zcu.gpa;
34853555
3486 zcu.clearCachedResolvedReferences();3556 zcu.clearCachedResolvedReferences();
...@@ -3500,6 +3570,7 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit...@@ -3500,6 +3570,7 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit
3500 .referenced = referenced_unit,3570 .referenced = referenced_unit,
3501 .next = if (gop.found_existing) gop.value_ptr.* else std.math.maxInt(u32),3571 .next = if (gop.found_existing) gop.value_ptr.* else std.math.maxInt(u32),
3502 .src = ref_src,3572 .src = ref_src,
3573 .inline_frame = inline_frame,
3503 };3574 };
35043575
3505 gop.value_ptr.* = @intCast(ref_idx);3576 gop.value_ptr.* = @intCast(ref_idx);
...@@ -3828,7 +3899,10 @@ pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionT...@@ -3828,7 +3899,10 @@ pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionT
38283899
3829pub const ResolvedReference = struct {3900pub const ResolvedReference = struct {
3830 referencer: AnalUnit,3901 referencer: AnalUnit,
3902 /// If `inline_frame` is not `.none`, this is the *deepest* source location in the chain of
3903 /// inline calls. For source locations further up the inline call stack, consult `inline_frame`.
3831 src: LazySrcLoc,3904 src: LazySrcLoc,
3905 inline_frame: InlineReferenceFrame.Index.Optional,
3832};3906};
38333907
3834/// Returns a mapping from an `AnalUnit` to where it is referenced.3908/// Returns a mapping from an `AnalUnit` to where it is referenced.
...@@ -4037,6 +4111,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4037,6 +4111,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4037 try unit_queue.put(gpa, ref.referenced, .{4111 try unit_queue.put(gpa, ref.referenced, .{
4038 .referencer = unit,4112 .referencer = unit,
4039 .src = ref.src,4113 .src = ref.src,
4114 .inline_frame = ref.inline_frame,
4040 });4115 });
4041 }4116 }
4042 ref_idx = ref.next;4117 ref_idx = ref.next;
...@@ -4055,6 +4130,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -4055,6 +4130,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
4055 try type_queue.put(gpa, ref.referenced, .{4130 try type_queue.put(gpa, ref.referenced, .{
4056 .referencer = unit,4131 .referencer = unit,
4057 .src = ref.src,4132 .src = ref.src,
4133 .inline_frame = .none,
4058 });4134 });
4059 }4135 }
4060 ref_idx = ref.next;4136 ref_idx = ref.next;
test/cases/compile_errors/add_overflow_in_function_evaluation.zig+1-3
...@@ -8,8 +8,6 @@ export fn entry() usize {...@@ -8,8 +8,6 @@ export fn entry() usize {
8}8}
99
10// error10// error
11// backend=stage2
12// target=native
13//11//
14// :3:14: error: overflow of integer type 'u16' with value '65540'12// :3:14: error: overflow of integer type 'u16' with value '65540'
15// :1:14: note: called from here13// :1:14: note: called at comptime here
test/cases/compile_errors/closure_get_depends_on_failed_decl.zig+1-3
...@@ -18,9 +18,7 @@ pub export fn entry() void {...@@ -18,9 +18,7 @@ pub export fn entry() void {
18}18}
1919
20// error20// error
21// backend=stage2
22// target=native
23//21//
24// :11:5: error: expected 0 argument(s), found 122// :11:5: error: expected 0 argument(s), found 1
25// :1:12: note: function declared here23// :1:12: note: function declared here
26// :17:19: note: called from here24// :17:19: note: called inline here
test/cases/compile_errors/compile_time_division_by_zero.zig+1-1
...@@ -10,4 +10,4 @@ export fn entry() usize {...@@ -10,4 +10,4 @@ export fn entry() usize {
10// error10// error
11//11//
12// :3:16: error: division by zero here causes illegal behavior12// :3:16: error: division by zero here causes illegal behavior
13// :1:14: note: called from here13// :1:14: note: called at comptime here
test/cases/compile_errors/comptime_try_non_error.zig+1-3
...@@ -11,8 +11,6 @@ pub fn bar() u8 {...@@ -11,8 +11,6 @@ pub fn bar() u8 {
11}11}
1212
13// error13// error
14// backend=stage2
15// target=native
16//14//
17// :6:12: error: expected error union type, found 'u8'15// :6:12: error: expected error union type, found 'u8'
18// :2:8: note: called from here16// :2:8: note: called at comptime here
test/cases/compile_errors/comptime_var_referenced_by_type.zig+1-1
...@@ -22,4 +22,4 @@ comptime {...@@ -22,4 +22,4 @@ comptime {
22//22//
23// :7:16: error: captured value contains reference to comptime var23// :7:16: error: captured value contains reference to comptime var
24// :16:30: note: 'wrapper.ptr' points to comptime var declared here24// :16:30: note: 'wrapper.ptr' points to comptime var declared here
25// :17:29: note: called from here25// :17:29: note: called at comptime here
test/cases/compile_errors/constant_inside_comptime_function_has_compile_error.zig+1-2
...@@ -15,9 +15,8 @@ export fn entry() void {...@@ -15,9 +15,8 @@ export fn entry() void {
15}15}
1616
17// error17// error
18// target=native
19//18//
20// :4:5: error: unreachable code19// :4:5: error: unreachable code
21// :4:25: note: control flow is diverted here20// :4:25: note: control flow is diverted here
22// :4:25: error: aoeu21// :4:25: error: aoeu
23// :1:36: note: called from here22// :1:36: note: called at comptime here
test/cases/compile_errors/error_in_comptime_call_in_container_level_initializer.zig+1-3
...@@ -15,8 +15,6 @@ pub export fn entry() void {...@@ -15,8 +15,6 @@ pub export fn entry() void {
15}15}
1616
17// error17// error
18// backend=stage2
19// target=native
20//18//
21// :9:48: error: caught unexpected error 'InvalidVersion'19// :9:48: error: caught unexpected error 'InvalidVersion'
22// :?:?: note: error returned here20// :?:?: note: error returned here
...@@ -24,4 +22,4 @@ pub export fn entry() void {...@@ -24,4 +22,4 @@ pub export fn entry() void {
24// :?:?: note: error returned here22// :?:?: note: error returned here
25// :?:?: note: error returned here23// :?:?: note: error returned here
26// :?:?: note: error returned here24// :?:?: note: error returned here
27// :12:37: note: called from here25// :12:37: note: called at comptime here
test/cases/compile_errors/generic_function_instantiation_inherits_parent_branch_quota.zig+2-2
...@@ -25,5 +25,5 @@ fn Type(comptime n: usize) type {...@@ -25,5 +25,5 @@ fn Type(comptime n: usize) type {
25//25//
26// :21:16: error: evaluation exceeded 1001 backwards branches26// :21:16: error: evaluation exceeded 1001 backwards branches
27// :21:16: note: use @setEvalBranchQuota() to raise the branch limit from 100127// :21:16: note: use @setEvalBranchQuota() to raise the branch limit from 1001
28// :16:34: note: called from here28// :16:34: note: called at comptime here
29// :8:15: note: called from here29// :8:15: note: generic function instantiated here
test/cases/compile_errors/generic_instantiation_failure_in_generic_function_return_type.zig+1-3
...@@ -36,8 +36,6 @@ pub fn is(comptime id: std.builtin.TypeId) TraitFn {...@@ -36,8 +36,6 @@ pub fn is(comptime id: std.builtin.TypeId) TraitFn {
36}36}
3737
38// error38// error
39// backend=stage2
40// target=native
41//39//
42// :8:48: error: expected type 'type', found 'bool'40// :8:48: error: expected type 'type', found 'bool'
43// :5:21: note: called from here41// :5:21: note: generic function instantiated here
test/cases/compile_errors/missing_main_fn_in_executable.zig+2-3
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1// error1// error
2// backend=stage2
3// target=x86_64-linux2// target=x86_64-linux
4// output_mode=Exe3// output_mode=Exe
5//4//
6// : error: root source file struct 'tmp' has no member named 'main'5// : error: root source file struct 'tmp' has no member named 'main'
7// : note: struct declared here6// : note: struct declared here
8// : note: called from here7// : note: called inline here
9// : note: called from here8// : note: called inline here
test/cases/compile_errors/missing_struct_field_in_fn_called_at_comptime.zig+1-3
...@@ -10,9 +10,7 @@ comptime {...@@ -10,9 +10,7 @@ comptime {
10}10}
1111
12// error12// error
13// backend=stage2
14// target=native
15//13//
16// :5:17: error: missing struct field: b14// :5:17: error: missing struct field: b
17// :1:11: note: struct declared here15// :1:11: note: struct declared here
18// :9:15: note: called from here16// :9:15: note: called at comptime here
test/cases/compile_errors/mul_overflow_in_function_evaluation.zig+1-3
...@@ -8,8 +8,6 @@ export fn entry() usize {...@@ -8,8 +8,6 @@ export fn entry() usize {
8}8}
99
10// error10// error
11// backend=stage2
12// target=native
13//11//
14// :3:14: error: overflow of integer type 'u16' with value '1800000'12// :3:14: error: overflow of integer type 'u16' with value '1800000'
15// :1:14: note: called from here13// :1:14: note: called at comptime here
test/cases/compile_errors/negation_overflow_in_function_evaluation.zig+1-3
...@@ -8,8 +8,6 @@ export fn entry() usize {...@@ -8,8 +8,6 @@ export fn entry() usize {
8}8}
99
10// error10// error
11// backend=stage2
12// target=native
13//11//
14// :3:12: error: overflow of integer type 'i8' with value '128'12// :3:12: error: overflow of integer type 'i8' with value '128'
15// :1:14: note: called from here13// :1:14: note: called at comptime here
test/cases/compile_errors/non-comptime-parameter-used-as-array-size.zig+1-1
...@@ -11,4 +11,4 @@ fn makeLlamas(count: usize) [count]u8 {}...@@ -11,4 +11,4 @@ fn makeLlamas(count: usize) [count]u8 {}
11//11//
12// :8:30: error: unable to resolve comptime value12// :8:30: error: unable to resolve comptime value
13// :8:30: note: array length must be comptime-known13// :8:30: note: array length must be comptime-known
14// :2:31: note: called from here14// :2:31: note: generic function instantiated here
test/cases/compile_errors/private_main_fn.zig+2-3
...@@ -1,11 +1,10 @@...@@ -1,11 +1,10 @@
1fn main() void {}1fn main() void {}
22
3// error3// error
4// backend=stage2
5// target=x86_64-linux4// target=x86_64-linux
6// output_mode=Exe5// output_mode=Exe
7//6//
8// : error: 'main' is not marked 'pub'7// : error: 'main' is not marked 'pub'
9// :1:1: note: declared here8// :1:1: note: declared here
10// : note: called from here9// : note: called inline here
11// : note: called from here10// : note: called inline here
test/cases/compile_errors/recursive_inline_fn.zig+4-4
...@@ -31,8 +31,8 @@ pub export fn entry2() void {...@@ -31,8 +31,8 @@ pub export fn entry2() void {
31// error31// error
32//32//
33// :5:27: error: inline call is recursive33// :5:27: error: inline call is recursive
34// :12:12: note: called from here34// :12:12: note: called inline here
35// :24:10: error: inline call is recursive35// :24:10: error: inline call is recursive
36// :20:10: note: called from here36// :20:10: note: called inline here
37// :16:11: note: called from here37// :16:11: note: called inline here
38// :28:10: note: called from here38// :28:10: note: called inline here
test/cases/compile_errors/referring_to_a_struct_that_is_invalid.zig+1-3
...@@ -11,8 +11,6 @@ fn assert(ok: bool) void {...@@ -11,8 +11,6 @@ fn assert(ok: bool) void {
11}11}
1212
13// error13// error
14// backend=stage2
15// target=native
16//14//
17// :10:14: error: reached unreachable code15// :10:14: error: reached unreachable code
18// :6:20: note: called from here16// :6:20: note: called at comptime here
test/cases/compile_errors/ret_coercion_error_in_generic_fn_called_from_non_fn_scope.zig+1-3
...@@ -6,9 +6,7 @@ comptime {...@@ -6,9 +6,7 @@ comptime {
6}6}
77
8// error8// error
9// backend=stage2
10// target=native
11//9//
12// :2:12: error: expected type 'fn () void', found 'type'10// :2:12: error: expected type 'fn () void', found 'type'
13// :1:10: note: function return type declared here11// :1:10: note: function return type declared here
14// :5:12: note: called from here12// :5:12: note: called at comptime here
test/cases/compile_errors/runtime_operation_in_comptime_scope.zig+1-1
...@@ -30,7 +30,7 @@ var rt: u32 = undefined;...@@ -30,7 +30,7 @@ var rt: u32 = undefined;
30// :10:12: note: call to function with comptime-only return type 'type' is evaluated at comptime30// :10:12: note: call to function with comptime-only return type 'type' is evaluated at comptime
31// :13:10: note: return type declared here31// :13:10: note: return type declared here
32// :10:12: note: types are not available at runtime32// :10:12: note: types are not available at runtime
33// :2:8: note: called from here33// :2:8: note: called inline here
34// :19:8: error: unable to evaluate comptime expression34// :19:8: error: unable to evaluate comptime expression
35// :19:5: note: operation is runtime due to this operand35// :19:5: note: operation is runtime due to this operand
36// :6:8: note: called at comptime from here36// :6:8: note: called at comptime from here
test/cases/compile_errors/sema_src_used_after_inline_call.zig+1-3
...@@ -18,9 +18,7 @@ export fn entry() void {...@@ -18,9 +18,7 @@ export fn entry() void {
18}18}
1919
20// error20// error
21// backend=stage2
22// target=native
23//21//
24// :13:30: error: expected type 'u32', found 'i32'22// :13:30: error: expected type 'u32', found 'i32'
25// :13:30: note: unsigned 32-bit int cannot represent all possible signed 32-bit values23// :13:30: note: unsigned 32-bit int cannot represent all possible signed 32-bit values
26// :17:33: note: called from here24// :17:33: note: called inline here
test/cases/compile_errors/stack_usage_in_naked_function.zig+1-2
...@@ -36,10 +36,9 @@ export fn d() callconv(.naked) noreturn {...@@ -36,10 +36,9 @@ export fn d() callconv(.naked) noreturn {
36}36}
3737
38// error38// error
39// backend=stage2
40//39//
41// :2:5: error: local variable in naked function40// :2:5: error: local variable in naked function
42// :10:5: error: local variable in naked function41// :10:5: error: local variable in naked function
43// :23:5: error: local variable in naked function42// :23:5: error: local variable in naked function
44// :30:13: error: local variable in naked function43// :30:13: error: local variable in naked function
45// :35:12: note: called from here44// :35:12: note: called inline here
test/cases/compile_errors/store_to_comptime_var_through_call.zig+1-1
...@@ -12,4 +12,4 @@ fn incr(x: *comptime_int) void {...@@ -12,4 +12,4 @@ fn incr(x: *comptime_int) void {
12//12//
13// :8:9: error: store to comptime variable depends on runtime condition13// :8:9: error: store to comptime variable depends on runtime condition
14// :3:9: note: runtime condition here14// :3:9: note: runtime condition here
15// :4:22: note: called from here15// :4:22: note: called at comptime here
test/cases/compile_errors/sub_overflow_in_function_evaluation.zig+1-3
...@@ -8,8 +8,6 @@ export fn entry() usize {...@@ -8,8 +8,6 @@ export fn entry() usize {
8}8}
99
10// error10// error
11// backend=stage2
12// target=native
13//11//
14// :3:14: error: overflow of integer type 'u16' with value '-10'12// :3:14: error: overflow of integer type 'u16' with value '-10'
15// :1:14: note: called from here13// :1:14: note: called at comptime here
test/cases/compile_errors/unreachable_executed_at_comptime.zig+1-3
...@@ -9,8 +9,6 @@ export fn entry() void {...@@ -9,8 +9,6 @@ export fn entry() void {
9}9}
1010
11// error11// error
12// backend=stage2
13// target=native
14//12//
15// :4:9: error: reached unreachable code13// :4:9: error: reached unreachable code
16// :8:21: note: called from here14// :8:21: note: called at comptime here