diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 9f420d217190..5072c4189f36 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -4481,11 +4481,18 @@ fn findTrackableInner( .func, .func_inferred, => { + const inst_data = datas[@intFromEnum(inst)].pl_node; + const extra = zir.extraData(Inst.Func, inst_data.payload_index); + + if (extra.data.body_len == 0) { + // This is just a prototype. No need to track. + assert(extra.data.ret_body_len < 2); + return; + } + assert(contents.func_decl == null); contents.func_decl = inst; - const inst_data = datas[@intFromEnum(inst)].pl_node; - const extra = zir.extraData(Inst.Func, inst_data.payload_index); var extra_index: usize = extra.end; switch (extra.data.ret_body_len) { 0 => {}, @@ -4500,11 +4507,19 @@ fn findTrackableInner( return zir.findTrackableBody(gpa, contents, defers, body); }, .func_fancy => { + const inst_data = datas[@intFromEnum(inst)].pl_node; + const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index); + + if (extra.data.body_len == 0) { + // This is just a prototype. No need to track. + assert(!extra.data.bits.has_cc_body); + assert(!extra.data.bits.has_ret_ty_body); + return; + } + assert(contents.func_decl == null); contents.func_decl = inst; - const inst_data = datas[@intFromEnum(inst)].pl_node; - const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index); var extra_index: usize = extra.end; if (extra.data.bits.has_cc_body) { @@ -5026,10 +5041,16 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void { .struct_init_ref, .struct_init_anon, => {}, // tracked in order, as the owner instructions of anonymous struct types - .func, - .func_inferred, - .func_fancy, - => {}, // tracked in order, as the owner instructions of function bodies + .func, .func_inferred => { + // These are tracked provided they are actual function declarations, not just bodies. + const extra = zir.extraData(Inst.Func, inst.data.pl_node.payload_index); + assert(extra.data.body_len != 0); + }, + .func_fancy => { + // These are tracked provided they are actual function declarations, not just bodies. + const extra = zir.extraData(Inst.FuncFancy, inst.data.pl_node.payload_index); + assert(extra.data.body_len != 0); + }, .declaration => {}, // tracked by correlating names in the namespace of the parent container .extended => switch (inst.data.extended.opcode) { .struct_decl, diff --git a/src/Compilation.zig b/src/Compilation.zig index cee9513ac53d..929ed586f65b 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3102,9 +3102,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { for (zcu.failed_embed_files.values()) |error_msg| { try addModuleErrorMsg(zcu, &bundle, error_msg.*); } - { + var sorted_failed_analysis: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: { const SortOrder = struct { zcu: *Zcu, + errors: []const *Zcu.ErrorMsg, err: *?Error, const Error = @typeInfo( @@ -3113,12 +3114,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { if (ctx.err.*) |_| return lhs_index < rhs_index; - const errors = ctx.zcu.failed_analysis.values(); - const lhs_src_loc = errors[lhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { + const lhs_src_loc = ctx.errors[lhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { // LHS source location lost, so should never be referenced. Just sort it to the end. return false; }; - const rhs_src_loc = errors[rhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { + const rhs_src_loc = ctx.errors[rhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { // RHS source location lost, so should never be referenced. Just sort it to the end. return true; }; @@ -3135,13 +3135,24 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { }).main; } }; + + // We can't directly sort `zcu.failed_analysis.entries`, because that would leave the map + // in an invalid state, and we need it intact for future incremental updates. The amount + // of data here is only as large as the number of analysis errors, so just dupe it all. + var entries = try zcu.failed_analysis.entries.clone(gpa); + errdefer entries.deinit(gpa); + var err: ?SortOrder.Error = null; - // This leaves `zcu.failed_analysis` an invalid state, but we do not - // need lookups anymore anyway. - zcu.failed_analysis.entries.sort(SortOrder{ .zcu = zcu, .err = &err }); + entries.sort(SortOrder{ + .zcu = zcu, + .errors = entries.items(.value), + .err = &err, + }); if (err) |e| return e; - } - for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| { + break :s entries.slice(); + }; + defer sorted_failed_analysis.deinit(gpa); + for (sorted_failed_analysis.items(.key), sorted_failed_analysis.items(.value)) |anal_unit, error_msg| { if (comp.incremental) { const refs = try zcu.resolveReferences(); if (!refs.contains(anal_unit)) continue; @@ -3158,6 +3169,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { // We'll try again once parsing succeeds. if (!zcu.fileByIndex(file_index).okToReportErrors()) continue; + std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{ + error_msg.msg, + zcu.fmtAnalUnit(anal_unit), + }); + try addModuleErrorMsg(zcu, &bundle, error_msg.*); if (zcu.cimport_errors.get(anal_unit)) |errors| { for (errors.getMessages()) |err_msg_index| { diff --git a/src/Zcu.zig b/src/Zcu.zig index 8b3125039ae2..fc6052a47c3c 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3590,17 +3590,17 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co const cu = ip.getComptimeUnit(cu_id); if (cu.zir_index.resolveFull(ip)) |resolved| { const file_path = zcu.fileByIndex(resolved.file).sub_file_path; - return writer.print("comptime(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) }); + return writer.print("comptime(inst=('{s}', %{}) [{}])", .{ file_path, @intFromEnum(resolved.inst), @intFromEnum(cu_id) }); } else { - return writer.writeAll("comptime(inst=)"); + return writer.print("comptime(inst= [{}])", .{@intFromEnum(cu_id)}); } }, - .nav_val => |nav| return writer.print("nav_val('{}')", .{ip.getNav(nav).fqn.fmt(ip)}), - .nav_ty => |nav| return writer.print("nav_ty('{}')", .{ip.getNav(nav).fqn.fmt(ip)}), - .type => |ty| return writer.print("ty('{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}), + .nav_val => |nav| return writer.print("nav_val('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), + .nav_ty => |nav| return writer.print("nav_ty('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), + .type => |ty| return writer.print("ty('{}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), .func => |func| { const nav = zcu.funcInfo(func).owner_nav; - return writer.print("func('{}')", .{ip.getNav(nav).fqn.fmt(ip)}); + return writer.print("func('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) }); }, } } diff --git a/test/incremental/fix_many_errors b/test/incremental/fix_many_errors new file mode 100644 index 000000000000..0722cdfced41 --- /dev/null +++ b/test/incremental/fix_many_errors @@ -0,0 +1,52 @@ +#target=x86_64-linux-selfhosted +#target=x86_64-linux-cbe +#target=x86_64-windows-cbe +#update=initial version +#file=main.zig +pub fn main() !void {} +comptime { @compileError("c0"); } +comptime { @compileError("c1"); } +comptime { @compileError("c2"); } +comptime { @compileError("c3"); } +comptime { @compileError("c4"); } +comptime { @compileError("c5"); } +comptime { @compileError("c6"); } +comptime { @compileError("c7"); } +comptime { @compileError("c8"); } +comptime { @compileError("c9"); } +export fn f0() void { @compileError("f0"); } +export fn f1() void { @compileError("f1"); } +export fn f2() void { @compileError("f2"); } +export fn f3() void { @compileError("f3"); } +export fn f4() void { @compileError("f4"); } +export fn f5() void { @compileError("f5"); } +export fn f6() void { @compileError("f6"); } +export fn f7() void { @compileError("f7"); } +export fn f8() void { @compileError("f8"); } +export fn f9() void { @compileError("f9"); } +#expect_error=ignored +#update=fix all the errors +#file=main.zig +pub fn main() !void {} +comptime {} +comptime {} +comptime {} +comptime {} +comptime {} +comptime {} +comptime {} +comptime {} +comptime {} +comptime {} +export fn f0() void {} +export fn f1() void {} +export fn f2() void {} +export fn f3() void {} +export fn f4() void {} +export fn f5() void {} +export fn f6() void {} +export fn f7() void {} +export fn f8() void {} +export fn f9() void {} +const std = @import("std"); +#expect_stdout=""