diff --git a/src/Compilation.zig b/src/Compilation.zig index 57e36bfbf7..d3cf9e8f38 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3681,32 +3681,27 @@ pub fn addModuleErrorMsg( const ref = maybe_ref orelse break; const gop = try seen.getOrPut(gpa, ref.referencer); if (gop.found_existing) break; - if (ref_traces.items.len < max_references) skip: { - const src = ref.src.upgrade(zcu); - const source = try src.file_scope.getSource(gpa); - const span = try src.span(gpa); - const loc = std.zig.findLineColumn(source.bytes, span.main); - const rt_file_path = try src.file_scope.fullPath(gpa); - defer gpa.free(rt_file_path); - const name = switch (ref.referencer.unwrap()) { + if (ref_traces.items.len < max_references) { + var last_call_src = ref.src; + var opt_inline_frame = ref.inline_frame; + while (opt_inline_frame.unwrap()) |inline_frame| { + const f = inline_frame.ptr(zcu).*; + const func_nav = ip.indexToKey(f.callee).func.owner_nav; + const func_name = ip.getNav(func_nav).name.toSlice(ip); + try addReferenceTraceFrame(zcu, eb, &ref_traces, func_name, last_call_src, true); + last_call_src = f.call_src; + opt_inline_frame = f.parent; + } + const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { .@"comptime" => "comptime", .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), - .memoized_state => break :skip, + .memoized_state => null, }; - try ref_traces.append(gpa, .{ - .decl_name = try eb.addString(name), - .src_loc = try eb.addSourceLocation(.{ - .src_path = try eb.addString(rt_file_path), - .span_start = span.start, - .span_main = span.main, - .span_end = span.end, - .line = @intCast(loc.line), - .column = @intCast(loc.column), - .source_line = 0, - }), - }); + if (root_name) |n| { + try addReferenceTraceFrame(zcu, eb, &ref_traces, n, last_call_src, false); + } } referenced_by = ref.referencer; } @@ -3786,6 +3781,35 @@ pub fn addModuleErrorMsg( } } +fn addReferenceTraceFrame( + zcu: *Zcu, + eb: *ErrorBundle.Wip, + ref_traces: *std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace), + name: []const u8, + lazy_src: Zcu.LazySrcLoc, + inlined: bool, +) !void { + const gpa = zcu.gpa; + const src = lazy_src.upgrade(zcu); + const source = try src.file_scope.getSource(gpa); + const span = try src.span(gpa); + const loc = std.zig.findLineColumn(source.bytes, span.main); + const rt_file_path = try src.file_scope.fullPath(gpa); + defer gpa.free(rt_file_path); + try ref_traces.append(gpa, .{ + .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(rt_file_path), + .span_start = span.start, + .span_main = span.main, + .span_end = span.end, + .line = @intCast(loc.line), + .column = @intCast(loc.column), + .source_line = 0, + }), + }); +} + pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void { const gpa = eb.gpa; const src_path = try file.fullPath(gpa); diff --git a/src/Sema.zig b/src/Sema.zig index e13aba3349..d267dcdb47 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -448,6 +448,21 @@ pub const Block = struct { func: InternPool.Index, comptime_result: Air.Inst.Ref, merges: Merges, + /// Populated lazily by `refFrame`. + ref_frame: Zcu.InlineReferenceFrame.Index.Optional = .none, + + fn refFrame(inlining: *Inlining, zcu: *Zcu) Allocator.Error!Zcu.InlineReferenceFrame.Index { + if (inlining.ref_frame == .none) { + inlining.ref_frame = (try zcu.addInlineReferenceFrame(.{ + .callee = inlining.func, + .call_src = inlining.call_src, + .parent = if (inlining.call_block.inlining) |parent_inlining| p: { + break :p (try parent_inlining.refFrame(zcu)).toOptional(); + } else .none, + })).toOptional(); + } + return inlining.ref_frame.unwrap().?; + } }; pub const Merges = struct { @@ -4287,7 +4302,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com if (zcu.intern_pool.isFuncBody(val)) { const ty = Type.fromInterned(zcu.intern_pool.typeOf(val)); if (try ty.fnHasRuntimeBitsSema(pt)) { - try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = val })); + try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = val })); try zcu.ensureFuncBodyAnalysisQueued(val); } } @@ -6615,7 +6630,7 @@ pub fn analyzeExport( if (options.linkage == .internal) return; - try sema.ensureNavResolved(src, orig_nav_index, .fully); + try sema.ensureNavResolved(block, src, orig_nav_index, .fully); const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) { .variable => |v| v.owner_nav, @@ -6644,7 +6659,7 @@ pub fn analyzeExport( return sema.fail(block, src, "export target cannot be extern", .{}); } - try sema.maybeQueueFuncBodyAnalysis(src, exported_nav_index); + try sema.maybeQueueFuncBodyAnalysis(block, src, exported_nav_index); try sema.exports.append(gpa, .{ .opts = options, @@ -6892,7 +6907,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .no_embedded_nulls, ); const nav_index = try sema.lookupIdentifier(block, src, decl_name); - return sema.analyzeNavRef(src, nav_index); + return sema.analyzeNavRef(block, src, nav_index); } fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -6988,7 +7003,7 @@ fn lookupInNamespace( } for (usingnamespaces.items) |sub_ns_nav| { - try sema.ensureNavResolved(src, sub_ns_nav, .fully); + try sema.ensureNavResolved(block, src, sub_ns_nav, .fully); const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val); const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu)); try checked_namespaces.put(gpa, sub_ns, {}); @@ -7720,8 +7735,8 @@ fn analyzeCall( var generic_inlining: Block.Inlining = if (func_ty_info.is_generic) .{ .call_block = block, .call_src = call_src, + .func = func_val.?.toIntern(), .has_comptime_args = false, // unused by error reporting - .func = .none, // unused by error reporting .comptime_result = .none, // unused by error reporting .merges = undefined, // unused because we'll never `return` } else undefined; @@ -7999,7 +8014,7 @@ fn analyzeCall( ref_func: { const runtime_func_val = try sema.resolveValue(runtime_func) orelse break :ref_func; if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func; - try sema.addReferenceEntry(call_src, .wrap(.{ .func = runtime_func_val.toIntern() })); + try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = runtime_func_val.toIntern() })); try zcu.ensureFuncBodyAnalysisQueued(runtime_func_val.toIntern()); } @@ -17254,7 +17269,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat .@"comptime" => |index| return Air.internedToRef(index), .runtime => |index| index, .nav_val => |nav| return sema.analyzeNavVal(block, src, nav), - .nav_ref => |nav| return sema.analyzeNavRef(src, nav), + .nav_ref => |nav| return sema.analyzeNavRef(block, src, nav), }; // The comptime case is handled already above. Runtime case below. @@ -18407,7 +18422,7 @@ fn typeInfoNamespaceDecls( if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) { continue; } - try sema.ensureNavResolved(src, nav, .fully); + try sema.ensureNavResolved(block, src, nav, .fully); const namespace_ty = Type.fromInterned(ip.getNav(nav).status.fully_resolved.val); try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces); } @@ -27932,7 +27947,7 @@ fn namespaceLookupRef( decl_name: InternPool.NullTerminatedString, ) CompileError!?Air.Inst.Ref { const nav = try sema.namespaceLookup(block, src, namespace, decl_name) orelse return null; - return try sema.analyzeNavRef(src, nav); + return try sema.analyzeNavRef(block, src, nav); } fn namespaceLookupVal( @@ -29095,7 +29110,7 @@ fn coerceExtra( .@"extern" => |e| e.owner_nav, else => unreachable, }; - const inst_as_ptr = try sema.analyzeNavRef(inst_src, fn_nav); + const inst_as_ptr = try sema.analyzeNavRef(block, inst_src, fn_nav); return sema.coerce(block, dest_ty, inst_as_ptr, inst_src); } @@ -30748,7 +30763,7 @@ fn coerceVarArgParam( .@"fn" => fn_ptr: { const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); const fn_nav = zcu.funcInfo(fn_val.toIntern()).owner_nav; - break :fn_ptr try sema.analyzeNavRef(inst_src, fn_nav); + break :fn_ptr try sema.analyzeNavRef(block, inst_src, fn_nav); }, .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}), .float => float: { @@ -31758,12 +31773,13 @@ fn analyzeNavVal( src: LazySrcLoc, nav_index: InternPool.Nav.Index, ) CompileError!Air.Inst.Ref { - const ref = try sema.analyzeNavRefInner(src, nav_index, false); + const ref = try sema.analyzeNavRefInner(block, src, nav_index, false); return sema.analyzeLoad(block, src, ref, src); } fn addReferenceEntry( sema: *Sema, + opt_block: ?*Block, src: LazySrcLoc, referenced_unit: AnalUnit, ) !void { @@ -31771,10 +31787,12 @@ fn addReferenceEntry( if (!zcu.comp.incremental and zcu.comp.reference_trace == 0) return; const gop = try sema.references.getOrPut(sema.gpa, referenced_unit); if (gop.found_existing) return; - // TODO: we need to figure out how to model inline calls here. - // They aren't references in the analysis sense, but ought to show up in the reference trace! - // Would representing inline calls in the reference table cause excessive memory usage? - try zcu.addUnitReference(sema.owner, referenced_unit, src); + try zcu.addUnitReference(sema.owner, referenced_unit, src, inline_frame: { + const block = opt_block orelse break :inline_frame .none; + const inlining = block.inlining orelse break :inline_frame .none; + const frame = try inlining.refFrame(zcu); + break :inline_frame frame.toOptional(); + }); } pub fn addTypeReferenceEntry( @@ -31793,7 +31811,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M const pt = sema.pt; const unit: AnalUnit = .wrap(.{ .memoized_state = stage }); - try sema.addReferenceEntry(src, unit); + try sema.addReferenceEntry(null, src, unit); try sema.declareDependency(.{ .memoized_state = stage }); if (pt.zcu.analysis_in_progress.contains(unit)) { @@ -31802,7 +31820,7 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M try pt.ensureMemoizedStateUpToDate(stage); } -pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void { +pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -31825,7 +31843,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav .type => .{ .nav_ty = nav_index }, .fully => .{ .nav_val = nav_index }, }); - try sema.addReferenceEntry(src, anal_unit); + try sema.addReferenceEntry(block, src, anal_unit); if (zcu.analysis_in_progress.contains(anal_unit)) { return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{ @@ -31855,25 +31873,25 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { } })); } -fn analyzeNavRef(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!Air.Inst.Ref { - return sema.analyzeNavRefInner(src, nav_index, true); +fn analyzeNavRef(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index) CompileError!Air.Inst.Ref { + return sema.analyzeNavRefInner(block, src, nav_index, true); } /// Analyze a reference to the `Nav` at the given index. Ensures the underlying `Nav` is analyzed. /// If this pointer will be used directly, `is_ref` must be `true`. /// If this pointer will be immediately loaded (i.e. a `decl_val` instruction), `is_ref` must be `false`. -fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, is_ref: bool) CompileError!Air.Inst.Ref { +fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_index: InternPool.Nav.Index, is_ref: bool) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - try sema.ensureNavResolved(src, orig_nav_index, if (is_ref) .type else .fully); + try sema.ensureNavResolved(block, src, orig_nav_index, if (is_ref) .type else .fully); const nav_index = nav: { if (ip.getNav(orig_nav_index).isExternOrFn(ip)) { // Getting a pointer to this `Nav` might mean we actually get a pointer to something else! // We need to resolve the value to know for sure. - if (is_ref) try sema.ensureNavResolved(src, orig_nav_index, .fully); + if (is_ref) try sema.ensureNavResolved(block, src, orig_nav_index, .fully); switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) { .func => |f| break :nav f.owner_nav, .@"extern" => |e| break :nav e.owner_nav, @@ -31897,7 +31915,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N }, }); if (is_ref) { - try sema.maybeQueueFuncBodyAnalysis(src, nav_index); + try sema.maybeQueueFuncBodyAnalysis(block, src, nav_index); } return Air.internedToRef((try pt.intern(.{ .ptr = .{ .ty = ptr_ty.toIntern(), @@ -31906,7 +31924,7 @@ fn analyzeNavRefInner(sema: *Sema, src: LazySrcLoc, orig_nav_index: InternPool.N } }))); } -fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void { +fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index) !void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -31914,16 +31932,16 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, nav_index: InternPoo // To avoid forcing too much resolution, let's first resolve the type, and check if it's a function. // If it is, we can resolve the *value*, and queue analysis as needed. - try sema.ensureNavResolved(src, nav_index, .type); + try sema.ensureNavResolved(block, src, nav_index, .type); const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip)); if (nav_ty.zigTypeTag(zcu) != .@"fn") return; if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return; - try sema.ensureNavResolved(src, nav_index, .fully); + try sema.ensureNavResolved(block, src, nav_index, .fully); const nav_val = zcu.navValue(nav_index); if (!ip.isFuncBody(nav_val.toIntern())) return; - try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = nav_val.toIntern() })); + try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = nav_val.toIntern() })); try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern()); } @@ -31939,8 +31957,8 @@ fn analyzeRef( if (try sema.resolveValue(operand)) |val| { switch (zcu.intern_pool.indexToKey(val.toIntern())) { - .@"extern" => |e| return sema.analyzeNavRef(src, e.owner_nav), - .func => |f| return sema.analyzeNavRef(src, f.owner_nav), + .@"extern" => |e| return sema.analyzeNavRef(block, src, e.owner_nav), + .func => |f| return sema.analyzeNavRef(block, src, f.owner_nav), else => return uavRef(sema, val.toIntern()), } } @@ -35504,7 +35522,7 @@ fn resolveInferredErrorSet( } // In this case we are dealing with the actual InferredErrorSet object that // corresponds to the function, not one created to track an inline/comptime call. - try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index })); + try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = func_index })); try pt.ensureFuncBodyUpToDate(func_index); } diff --git a/src/Sema/comptime_ptr_access.zig b/src/Sema/comptime_ptr_access.zig index 2e21c31f2b..f4ac897154 100644 --- a/src/Sema/comptime_ptr_access.zig +++ b/src/Sema/comptime_ptr_access.zig @@ -228,7 +228,7 @@ fn loadComptimePtrInner( const base_val: MutableValue = switch (ptr.base_addr) { .nav => |nav| val: { - try sema.ensureNavResolved(src, nav, .fully); + try sema.ensureNavResolved(block, src, nav, .fully); const val = ip.getNav(nav).status.fully_resolved.val; switch (ip.indexToKey(val)) { .variable => return .runtime_load, diff --git a/src/Zcu.zig b/src/Zcu.zig index fab40763e8..584eb8ca3d 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -215,6 +215,9 @@ all_references: std.ArrayListUnmanaged(Reference) = .empty, /// Freelist of indices in `all_references`. free_references: std.ArrayListUnmanaged(u32) = .empty, +inline_reference_frames: std.ArrayListUnmanaged(InlineReferenceFrame) = .empty, +free_inline_reference_frames: std.ArrayListUnmanaged(InlineReferenceFrame.Index) = .empty, + /// Key is the `AnalUnit` *performing* the reference. This representation allows /// incremental updates to quickly delete references caused by a specific `AnalUnit`. /// Value is index into `all_type_reference` of the first reference triggered by the unit. @@ -583,6 +586,42 @@ pub const Reference = struct { next: u32, /// The source location of the reference. src: LazySrcLoc, + /// If not `.none`, this is the index of the `InlineReferenceFrame` which should appear + /// between the referencer and `referenced` in the reference trace. These frames represent + /// inline calls, which do not create actual references (since they happen in the caller's + /// `AnalUnit`), but do show in the reference trace. + inline_frame: InlineReferenceFrame.Index.Optional, +}; + +pub const InlineReferenceFrame = struct { + /// The inline *callee*; that is, the function which was called inline. + /// The *caller* is either `parent`, or else the unit causing the original `Reference`. + callee: InternPool.Index, + /// The source location of the inline call, in the *caller*. + call_src: LazySrcLoc, + /// If not `.none`, a frame which should appear directly below this one. + /// This will be the "parent" inline call; this frame's `callee` is our caller. + parent: InlineReferenceFrame.Index.Optional, + + pub const Index = enum(u32) { + _, + pub fn ptr(idx: Index, zcu: *Zcu) *InlineReferenceFrame { + return &zcu.inline_reference_frames.items[@intFromEnum(idx)]; + } + pub fn toOptional(idx: Index) Optional { + return @enumFromInt(@intFromEnum(idx)); + } + pub const Optional = enum(u32) { + none = std.math.maxInt(u32), + _, + pub fn unwrap(opt: Optional) ?Index { + return switch (opt) { + .none => null, + _ => @enumFromInt(@intFromEnum(opt)), + }; + } + }; + }; }; pub const TypeReference = struct { @@ -3440,12 +3479,28 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { var idx = kv.value; while (idx != std.math.maxInt(u32)) { + const ref = zcu.all_references.items[idx]; zcu.free_references.append(gpa, idx) catch { // This space will be reused eventually, so we need not propagate this error. // Just leak it for now, and let GC reclaim it later on. break :unit_refs; }; - idx = zcu.all_references.items[idx].next; + idx = ref.next; + + var opt_inline_frame = ref.inline_frame; + while (opt_inline_frame.unwrap()) |inline_frame| { + // The same inline frame could be used multiple times by one unit. We need to + // detect this case to avoid adding it to `free_inline_reference_frames` more + // than once. We do that by setting `parent` to itself as a marker. + if (inline_frame.ptr(zcu).parent == inline_frame.toOptional()) break; + zcu.free_inline_reference_frames.append(gpa, inline_frame) catch { + // This space will be reused eventually, so we need not propagate this error. + // Just leak it for now, and let GC reclaim it later on. + break :unit_refs; + }; + opt_inline_frame = inline_frame.ptr(zcu).parent; + inline_frame.ptr(zcu).parent = inline_frame.toOptional(); // signal to code above + } } } @@ -3480,7 +3535,22 @@ pub fn deleteUnitCompileLogs(zcu: *Zcu, anal_unit: AnalUnit) void { } } -pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void { +pub fn addInlineReferenceFrame(zcu: *Zcu, frame: InlineReferenceFrame) Allocator.Error!Zcu.InlineReferenceFrame.Index { + const frame_idx: InlineReferenceFrame.Index = zcu.free_inline_reference_frames.pop() orelse idx: { + _ = try zcu.inline_reference_frames.addOne(zcu.gpa); + break :idx @enumFromInt(zcu.inline_reference_frames.items.len - 1); + }; + frame_idx.ptr(zcu).* = frame; + return frame_idx; +} + +pub fn addUnitReference( + zcu: *Zcu, + src_unit: AnalUnit, + referenced_unit: AnalUnit, + ref_src: LazySrcLoc, + inline_frame: InlineReferenceFrame.Index.Optional, +) Allocator.Error!void { const gpa = zcu.gpa; zcu.clearCachedResolvedReferences(); @@ -3500,6 +3570,7 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit .referenced = referenced_unit, .next = if (gop.found_existing) gop.value_ptr.* else std.math.maxInt(u32), .src = ref_src, + .inline_frame = inline_frame, }; gop.value_ptr.* = @intCast(ref_idx); @@ -3828,7 +3899,10 @@ pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionT pub const ResolvedReference = struct { referencer: AnalUnit, + /// If `inline_frame` is not `.none`, this is the *deepest* source location in the chain of + /// inline calls. For source locations further up the inline call stack, consult `inline_frame`. src: LazySrcLoc, + inline_frame: InlineReferenceFrame.Index.Optional, }; /// Returns a mapping from an `AnalUnit` to where it is referenced. @@ -4037,6 +4111,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv try unit_queue.put(gpa, ref.referenced, .{ .referencer = unit, .src = ref.src, + .inline_frame = ref.inline_frame, }); } ref_idx = ref.next; @@ -4055,6 +4130,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv try type_queue.put(gpa, ref.referenced, .{ .referencer = unit, .src = ref.src, + .inline_frame = .none, }); } ref_idx = ref.next;