Sema: fix unreasonable progress node numbers

The "completed" count in the "Semantic Analysis" progress node had
regressed since 0.14.0: the number got crazy big very fast, even on
simple cases. For instance, an empty `pub fn main` got to ~59,000 where
on 0.14 it only reached ~4,000. This was happening because I was
unintentionally introducing a node every time type resolution was
*requested*, even if (as is usually the case) it turned out to already
be done. The fix is simply to start the progress node a little later,
once we know we are actually doing semantic analysis. This brings the
number for that empty test case down to ~5,000, which makes perfect
sense. It won't exactly match 0.14, because the standard library has
changed, and also because the compiler's progress output does have some
*intentional* changes.
This commit is contained in:
mlugg 2025-08-08 09:13:38 +01:00 committed by Matthew Lugg
parent 2a8751e37f
commit 5f7a0bbabf
2 changed files with 30 additions and 6 deletions

View file

@ -34199,6 +34199,9 @@ pub fn resolveStructAlignment(
if (struct_type.assumePointerAlignedIfWip(ip, ptr_align)) return;
defer struct_type.clearAlignmentWip(ip);
// No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
// It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
var alignment: Alignment = .@"1";
for (0..struct_type.field_types.len) |i| {
@ -34229,6 +34232,9 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
try sema.resolveStructFieldTypes(ty.toIntern(), struct_type);
// No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
// It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
if (struct_type.layout == .@"packed") {
sema.backingIntType(struct_type) catch |err| switch (err) {
error.OutOfMemory, error.AnalysisFail => |e| return e,
@ -34532,6 +34538,9 @@ pub fn resolveUnionAlignment(
try sema.resolveUnionFieldTypes(ty, union_type);
// No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
// It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
var max_align: Alignment = .@"1";
for (0..union_type.field_types.len) |field_index| {
const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]);
@ -34579,6 +34588,9 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
union_type.setStatus(ip, .layout_wip);
// No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
// It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
var max_size: u64 = 0;
var max_align: Alignment = .@"1";
for (0..union_type.field_types.len) |field_index| {
@ -34695,6 +34707,9 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
if (struct_type.setFullyResolved(ip)) return;
errdefer struct_type.clearFullyResolved(ip);
// No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
// It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
// After we have resolve struct layout we have to go over the fields again to
// make sure pointer fields get their child types resolved as well.
// See also similar code for unions.
@ -34720,6 +34735,9 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
.fully_resolved_wip, .fully_resolved => return,
}
// No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
// It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
{
// After we have resolve union layout we have to go over the fields again to
// make sure pointer fields get their child types resolved as well.
@ -34762,6 +34780,10 @@ pub fn resolveStructFieldTypes(
}
defer struct_type.clearFieldTypesWip(ip);
// can't happen earlier than this because we only want the progress node if not already resolved
const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);
defer tracked_unit.end(zcu);
sema.structFields(struct_type) catch |err| switch (err) {
error.AnalysisFail, error.OutOfMemory => |e| return e,
error.ComptimeBreak, error.ComptimeReturn => unreachable,
@ -34791,6 +34813,10 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
}
defer struct_type.clearInitsWip(ip);
// can't happen earlier than this because we only want the progress node if not already resolved
const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);
defer tracked_unit.end(zcu);
sema.structFieldInits(struct_type) catch |err| switch (err) {
error.AnalysisFail, error.OutOfMemory => |e| return e,
error.ComptimeBreak, error.ComptimeReturn => unreachable,
@ -34819,6 +34845,10 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
=> return,
}
// can't happen earlier than this because we only want the progress node if not already resolved
const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null);
defer tracked_unit.end(zcu);
union_type.setStatus(ip, .field_types_wip);
errdefer union_type.setStatus(ip, .none);
sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) {

View file

@ -3797,9 +3797,6 @@ fn resolveStructInner(
return error.AnalysisFail;
}
const tracked_unit = zcu.trackUnitSema(struct_obj.name.toSlice(&zcu.intern_pool), null);
defer tracked_unit.end(zcu);
if (zcu.comp.debugIncremental()) {
const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner);
info.last_update_gen = zcu.generation;
@ -3859,9 +3856,6 @@ fn resolveUnionInner(
return error.AnalysisFail;
}
const tracked_unit = zcu.trackUnitSema(union_obj.name.toSlice(&zcu.intern_pool), null);
defer tracked_unit.end(zcu);
if (zcu.comp.debugIncremental()) {
const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner);
info.last_update_gen = zcu.generation;