Zcu: fix analysis of type of decl with inferred type

If the `nav_ty` is resolved by the `nav_val`, then we need to also mark
the `nav_ty` as in progress when we begin resolving the `nav_val`.
This commit is contained in:
mlugg 2025-09-10 12:48:42 +01:00 committed by Andrew Kelley
parent d7d50496d9
commit 2f9d8d5a9b
2 changed files with 25 additions and 9 deletions

View File

@ -34990,7 +34990,7 @@ fn resolveInferredErrorSet(
const resolved_ty = func.resolvedErrorSetUnordered(ip);
if (resolved_ty != .none) return resolved_ty;
if (zcu.analysis_in_progress.contains(AnalUnit.wrap(.{ .func = func_index }))) {
if (zcu.analysis_in_progress.contains(.wrap(.{ .func = func_index }))) {
return sema.fail(block, src, "unable to resolve inferred error set", .{});
}

View File

@ -700,7 +700,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)
const unit: AnalUnit = .wrap(.{ .memoized_state = stage });
try zcu.analysis_in_progress.put(gpa, unit, {});
try zcu.analysis_in_progress.putNoClobber(gpa, unit, {});
defer assert(zcu.analysis_in_progress.swapRemove(unit));
// Before we begin, collect:
@ -864,7 +864,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
const file = zcu.fileByIndex(inst_resolved.file);
const zir = file.zir.?;
try zcu.analysis_in_progress.put(gpa, anal_unit, {});
try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {});
defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
@ -958,6 +958,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu
log.debug("ensureNavValUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
assert(!zcu.analysis_in_progress.contains(anal_unit));
// Determine whether or not this `Nav`'s value is outdated. This also includes checking if the
// status is `.unresolved`, which indicates that the value is outdated because it has *never*
// been analyzed so far.
@ -1090,10 +1092,19 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
const file = zcu.fileByIndex(inst_resolved.file);
const zir = file.zir.?;
const zir_decl = zir.getDeclaration(inst_resolved.inst);
try zcu.analysis_in_progress.put(gpa, anal_unit, {});
try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {});
errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
// If there's no type body, we are also resolving the type here.
if (zir_decl.type_body == null) {
try zcu.analysis_in_progress.putNoClobber(gpa, .wrap(.{ .nav_ty = nav_id }), {});
}
errdefer if (zir_decl.type_body == null) {
_ = zcu.analysis_in_progress.swapRemove(.wrap(.{ .nav_ty = nav_id }));
};
var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
defer analysis_arena.deinit();
@ -1133,8 +1144,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
};
defer block.instructions.deinit(gpa);
const zir_decl = zir.getDeclaration(inst_resolved.inst);
const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero });
const init_src = block.src(.{ .node_offset_var_decl_init = .zero });
const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
@ -1305,6 +1314,9 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
// Mark the unit as completed before evaluating the export!
assert(zcu.analysis_in_progress.swapRemove(anal_unit));
if (zir_decl.type_body == null) {
assert(zcu.analysis_in_progress.swapRemove(.wrap(.{ .nav_ty = nav_id })));
}
if (zir_decl.linkage == .@"export") {
const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) });
@ -1347,6 +1359,8 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc
log.debug("ensureNavTypeUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
assert(!zcu.analysis_in_progress.contains(anal_unit));
const type_resolved_by_value: bool = from_val: {
const analysis = nav.analysis orelse break :from_val false;
const inst_resolved = analysis.zir_index.resolveFull(ip) orelse break :from_val false;
@ -1463,8 +1477,8 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
const file = zcu.fileByIndex(inst_resolved.file);
const zir = file.zir.?;
try zcu.analysis_in_progress.put(gpa, anal_unit, {});
defer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {});
defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
const zir_decl = zir.getDeclaration(inst_resolved.inst);
const type_body = zir_decl.type_body.?;
@ -1587,6 +1601,8 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z
log.debug("ensureFuncBodyUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
assert(!zcu.analysis_in_progress.contains(anal_unit));
const func = zcu.funcInfo(func_index);
assert(func.ty == func.uncoerced_ty); // analyze the body of the original function, not a coerced one
@ -2781,7 +2797,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
const file = zcu.fileByIndex(inst_info.file);
const zir = file.zir.?;
try zcu.analysis_in_progress.put(gpa, anal_unit, {});
try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {});
errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
func.setAnalyzed(ip);