diff --git a/src/Compilation.zig b/src/Compilation.zig index 069cc8a2c7..6cc8502461 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2858,51 +2858,52 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .{}; defer ref_traces.deinit(gpa); - for (module_err_msg.reference_trace) |module_reference| { - if (module_reference.hidden != 0) { - try ref_traces.append(gpa, .{ - .decl_name = module_reference.hidden, - .src_loc = .none, - }); - break; - } else if (module_reference.decl == .none) { - try ref_traces.append(gpa, .{ - .decl_name = 0, - .src_loc = .none, - }); - break; + const remaining_references: ?u32 = remaining: { + if (mod.comp.reference_trace) |_| { + if (module_err_msg.hidden_references > 0) break :remaining module_err_msg.hidden_references; + } else { + if (module_err_msg.reference_trace.len > 0) break :remaining 0; } + break :remaining null; + }; + try ref_traces.ensureTotalCapacityPrecise(gpa, module_err_msg.reference_trace.len + + @intFromBool(remaining_references != null)); + + for (module_err_msg.reference_trace) |module_reference| { const source = try module_reference.src_loc.file_scope.getSource(gpa); const span = try module_reference.src_loc.span(gpa); const loc = std.zig.findLineColumn(source.bytes, span.main); const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa); defer gpa.free(rt_file_path); - try ref_traces.append(gpa, .{ - .decl_name = try eb.addString(ip.stringToSliceUnwrap(module_reference.decl).?), + ref_traces.appendAssumeCapacity(.{ + .decl_name = try eb.addString(ip.stringToSlice(module_reference.decl)), .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 = @as(u32, @intCast(loc.line)), - .column = @as(u32, @intCast(loc.column)), + .line = @intCast(loc.line), + .column = @intCast(loc.column), .source_line = 0, }), }); } + if (remaining_references) |remaining| ref_traces.appendAssumeCapacity( + .{ .decl_name = remaining, .src_loc = .none }, + ); const src_loc = try eb.addSourceLocation(.{ .src_path = try eb.addString(file_path), .span_start = err_span.start, .span_main = err_span.main, .span_end = err_span.end, - .line = @as(u32, @intCast(err_loc.line)), - .column = @as(u32, @intCast(err_loc.column)), + .line = @intCast(err_loc.line), + .column = @intCast(err_loc.column), .source_line = if (module_err_msg.src_loc.lazy == .entire_file) 0 else try eb.addString(err_loc.source_line), - .reference_trace_len = @as(u32, @intCast(ref_traces.items.len)), + .reference_trace_len = @intCast(ref_traces.items.len), }); for (ref_traces.items) |rt| { @@ -2928,8 +2929,8 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod .span_start = span.start, .span_main = span.main, .span_end = span.end, - .line = @as(u32, @intCast(loc.line)), - .column = @as(u32, @intCast(loc.column)), + .line = @intCast(loc.line), + .column = @intCast(loc.column), .source_line = if (err_loc.eql(loc)) 0 else try eb.addString(loc.source_line), }), }, .{ .eb = eb }); @@ -2938,7 +2939,7 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod } } - const notes_len = @as(u32, @intCast(notes.entries.len)); + const notes_len: u32 = @intCast(notes.entries.len); try eb.addRootErrorMessage(.{ .msg = try eb.addString(module_err_msg.msg), diff --git a/src/Module.zig b/src/Module.zig index d1b1e9b357..ba76c16faf 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1519,11 +1519,11 @@ pub const ErrorMsg = struct { msg: []const u8, notes: []ErrorMsg = &.{}, reference_trace: []Trace = &.{}, + hidden_references: u32 = 0, pub const Trace = struct { - decl: InternPool.OptionalNullTerminatedString, + decl: InternPool.NullTerminatedString, src_loc: SrcLoc, - hidden: u32 = 0, }; pub fn create( diff --git a/src/Sema.zig b/src/Sema.zig index dc60238423..b843081a6a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2396,80 +2396,69 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) const gpa = sema.gpa; const mod = sema.mod; - if (crash_report.is_enabled and mod.comp.debug_compile_errors) { - if (err_msg.src_loc.lazy == .unneeded) return error.NeededSourceLocation; - var wip_errors: std.zig.ErrorBundle.Wip = undefined; - wip_errors.init(gpa) catch unreachable; - Compilation.addModuleErrorMsg(mod, &wip_errors, err_msg.*) catch unreachable; - std.debug.print("compile error during Sema:\n", .{}); - var error_bundle = wip_errors.toOwnedBundle("") catch unreachable; - error_bundle.renderToStdErr(.{ .ttyconf = .no_color }); - crash_report.compilerPanic("unexpected compile error occurred", null, null); - } - ref: { errdefer err_msg.destroy(gpa); - if (err_msg.src_loc.lazy == .unneeded) { - return error.NeededSourceLocation; + if (err_msg.src_loc.lazy == .unneeded) return error.NeededSourceLocation; + + if (crash_report.is_enabled and mod.comp.debug_compile_errors) { + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + wip_errors.init(gpa) catch unreachable; + Compilation.addModuleErrorMsg(mod, &wip_errors, err_msg.*) catch unreachable; + std.debug.print("compile error during Sema:\n", .{}); + var error_bundle = wip_errors.toOwnedBundle("") catch unreachable; + error_bundle.renderToStdErr(.{ .ttyconf = .no_color }); + crash_report.compilerPanic("unexpected compile error occurred", null, null); } + try mod.failed_decls.ensureUnusedCapacity(gpa, 1); try mod.failed_files.ensureUnusedCapacity(gpa, 1); - var func_index: InternPool.Index = .none; if (block) |start_block| { var block_it = start_block; while (block_it.inlining) |inlining| { - func_index = inlining.func; + try sema.errNote( + inlining.call_block, + inlining.call_src, + err_msg, + "called from here", + .{}, + ); block_it = inlining.call_block; - try sema.errNote(block_it, inlining.call_src, err_msg, "called from here", .{}); } - } - const max_references = blk: { - if (mod.comp.reference_trace) |num| break :blk num; - // Do not add multiple traces without explicit request. - if (mod.failed_decls.count() != 0) break :ref; - break :blk default_reference_trace_len; - }; + const max_references = refs: { + if (mod.comp.reference_trace) |num| break :refs num; + // Do not add multiple traces without explicit request. + if (mod.failed_decls.count() > 0) break :ref; + break :refs default_reference_trace_len; + }; - var referenced_by = if (sema.owner_func_index != .none) - mod.funcOwnerDeclIndex(sema.owner_func_index) - else - sema.owner_decl_index; - var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa); - defer reference_stack.deinit(); + var referenced_by = if (sema.owner_func_index != .none) + mod.funcOwnerDeclIndex(sema.owner_func_index) + else + sema.owner_decl_index; + var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa); + defer reference_stack.deinit(); - // Avoid infinite loops. - var seen = std.AutoHashMap(Decl.Index, void).init(gpa); - defer seen.deinit(); + // Avoid infinite loops. + var seen = std.AutoHashMap(Decl.Index, void).init(gpa); + defer seen.deinit(); - var cur_reference_trace: u32 = 0; - while (sema.mod.reference_table.get(referenced_by)) |ref| : (cur_reference_trace += 1) { - const gop = try seen.getOrPut(ref.referencer); - if (gop.found_existing) break; - if (cur_reference_trace < max_references) { - const decl = sema.mod.declPtr(ref.referencer); - try reference_stack.append(.{ - .decl = decl.name.toOptional(), - .src_loc = ref.src.toSrcLoc(decl, mod), - }); + while (mod.reference_table.get(referenced_by)) |ref| { + const gop = try seen.getOrPut(ref.referencer); + if (gop.found_existing) break; + if (reference_stack.items.len < max_references) { + const decl = mod.declPtr(ref.referencer); + try reference_stack.append(.{ + .decl = decl.name, + .src_loc = ref.src.toSrcLoc(decl, mod), + }); + } + referenced_by = ref.referencer; } - referenced_by = ref.referencer; + err_msg.reference_trace = try reference_stack.toOwnedSlice(); + err_msg.hidden_references = @intCast(seen.count() -| max_references); } - if (sema.mod.comp.reference_trace == null and cur_reference_trace > 0) { - try reference_stack.append(.{ - .decl = .none, - .src_loc = undefined, - .hidden = 0, - }); - } else if (cur_reference_trace > max_references) { - try reference_stack.append(.{ - .decl = undefined, - .src_loc = undefined, - .hidden = cur_reference_trace - max_references, - }); - } - err_msg.reference_trace = try reference_stack.toOwnedSlice(); } const ip = &mod.intern_pool; if (sema.owner_func_index != .none) { @@ -7399,7 +7388,8 @@ fn analyzeCall( var block_it = block; while (block_it.inlining) |parent_inlining| { if (!parent_inlining.has_comptime_args and parent_inlining.func == module_fn_index) { - return sema.fail(block, call_src, "inline call is recursive", .{}); + const err_msg = try sema.errMsg(block, call_src, "inline call is recursive", .{}); + return sema.failWithOwnedErrorMsg(null, err_msg); } block_it = parent_inlining.call_block; } diff --git a/test/cases/compile_errors/recursive_inline_fn.zig b/test/cases/compile_errors/recursive_inline_fn.zig index 2308bbdbc7..67184271eb 100644 --- a/test/cases/compile_errors/recursive_inline_fn.zig +++ b/test/cases/compile_errors/recursive_inline_fn.zig @@ -11,8 +11,25 @@ pub export fn entry() void { _ = foo(x) == 20; } +inline fn first() void { + second(); +} + +inline fn second() void { + third(); +} + +inline fn third() void { + first(); +} + +pub export fn entry2() void { + first(); +} + // error // backend=stage2 // target=native // // :5:27: error: inline call is recursive +// :23:10: error: inline call is recursive