authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-08-08 15:07:03+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-08-08 22:37:27+01:00
log1440519239516f0b16a5cc7094aa3997f4b508f5
treee82d2826665e5d1116c73d57b41432aa63d46813
parent3d25a9c1e07cfcb72250760b2c1a1d9d4f6174ed

compiler: improve error reporting

The functions `Compilation.create` and `Compilation.update` previously returned inferred error sets, which had built up a lot of crap over time. This meant that certain error conditions -- particularly certain filesystem errors -- were not being reported properly (at best the CLI would just print the error name). This was also a problem in sub-compilations, where at times only the error name -- which might just be something like `LinkFailed` -- would be visible. This commit makes the error handling here more disciplined by introducing concrete error sets to these functions (and a few more as a consequence). These error sets are small: errors in `update` are almost all reported via compile errors, and errors in `create` are reported through a new `Compilation.CreateDiagnostic` type, a tagged union of possible error cases. This allows for better error reporting. Sub-compilations also report errors more correctly in several cases, leading to more informative errors in the case of compiler bugs. Also fixes some race conditions in library building by replacing calls to `setMiscFailure` with calls to `lockAndSetMiscFailure`. Compilation of libraries such as libc happens on the thread pool, so the logic must synchronize its access to shared `Compilation` state.

16 files changed, 647 insertions(+), 345 deletions(-)

lib/std/zig/LibCDirs.zig+2-2
......@@ -19,7 +19,7 @@ pub fn detect(
1919 is_native_abi: bool,
2020 link_libc: bool,
2121 libc_installation: ?*const LibCInstallation,
22) !LibCDirs {
22) LibCInstallation.FindError!LibCDirs {
2323 if (!link_libc) {
2424 return .{
2525 .libc_include_dir_list = &[0][]u8{},
......@@ -114,7 +114,7 @@ fn detectFromInstallation(arena: Allocator, target: *const std.Target, lci: *con
114114 }
115115 }
116116 if (target.os.tag == .haiku) {
117 const include_dir_path = lci.include_dir orelse return error.LibCInstallationNotAvailable;
117 const include_dir_path = lci.include_dir.?;
118118 const os_dir = try std.fs.path.join(arena, &[_][]const u8{ include_dir_path, "os" });
119119 list.appendAssumeCapacity(os_dir);
120120 // Errors.h
src/Compilation.zig+410-180
......@@ -1391,6 +1391,7 @@ pub const Win32Resource = struct {
13911391};
13921392
13931393pub const MiscTask = enum {
1394 open_output,
13941395 write_builtin_zig,
13951396 rename_results,
13961397 check_whole_cache,
......@@ -1874,7 +1875,49 @@ fn addModuleTableToCacheHash(
18741875
18751876const RtStrat = enum { none, lib, obj, zcu, dyn_lib };
18761877
1877pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compilation {
1878pub const CreateDiagnostic = union(enum) {
1879 export_table_import_table_conflict,
1880 emit_h_without_zcu,
1881 illegal_zig_import,
1882 cross_libc_unavailable,
1883 find_native_libc: std.zig.LibCInstallation.FindError,
1884 libc_installation_missing_crt_dir,
1885 create_cache_path: CreateCachePath,
1886 open_output_bin: link.File.OpenError,
1887 pub const CreateCachePath = struct {
1888 which: enum { local, global },
1889 sub: []const u8,
1890 err: (fs.Dir.MakeError || fs.Dir.OpenError || fs.Dir.StatFileError),
1891 };
1892 pub fn format(diag: CreateDiagnostic, w: *std.Io.Writer) std.Io.Writer.Error!void {
1893 switch (diag) {
1894 .export_table_import_table_conflict => try w.writeAll("'--import-table' and '--export-table' cannot be used together"),
1895 .emit_h_without_zcu => try w.writeAll("cannot emit C header with no Zig source files"),
1896 .illegal_zig_import => try w.writeAll("this compiler implementation does not support importing the root source file of a provided module"),
1897 .cross_libc_unavailable => try w.writeAll("unable to provide libc for this target"),
1898 .find_native_libc => |err| try w.print("failed to find libc installation: {t}", .{err}),
1899 .libc_installation_missing_crt_dir => try w.writeAll("libc installation is missing crt directory"),
1900 .create_cache_path => |cache| try w.print("failed to create path '{s}' in {t} cache directory: {t}", .{
1901 cache.sub,
1902 cache.which,
1903 cache.err,
1904 }),
1905 .open_output_bin => |err| try w.print("failed to open output binary: {t}", .{err}),
1906 }
1907 }
1908
1909 fn fail(out: *CreateDiagnostic, result: CreateDiagnostic) error{CreateFail} {
1910 out.* = result;
1911 return error.CreateFail;
1912 }
1913};
1914pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options: CreateOptions) error{
1915 OutOfMemory,
1916 Unexpected,
1917 CurrentWorkingDirectoryUnlinked,
1918 /// An error has been stored to `diag`.
1919 CreateFail,
1920}!*Compilation {
18781921 const output_mode = options.config.output_mode;
18791922 const is_dyn_lib = switch (output_mode) {
18801923 .Obj, .Exe => false,
......@@ -1887,7 +1930,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18871930 };
18881931
18891932 if (options.linker_export_table and options.linker_import_table) {
1890 return error.ExportTableAndImportTableConflict;
1933 return diag.fail(.export_table_import_table_conflict);
18911934 }
18921935
18931936 const have_zcu = options.config.have_zcu;
......@@ -1920,14 +1963,18 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19201963
19211964 const link_libc = options.config.link_libc;
19221965
1923 const libc_dirs = try std.zig.LibCDirs.detect(
1966 const libc_dirs = std.zig.LibCDirs.detect(
19241967 arena,
19251968 options.dirs.zig_lib.path.?,
19261969 target,
19271970 options.root_mod.resolved_target.is_native_abi,
19281971 link_libc,
19291972 options.libc_installation,
1930 );
1973 ) catch |err| switch (err) {
1974 error.OutOfMemory => |e| return e,
1975 // Every other error is specifically related to finding the native installation
1976 else => |e| return diag.fail(.{ .find_native_libc = e }),
1977 };
19311978
19321979 const sysroot = options.sysroot orelse libc_dirs.sysroot;
19331980
......@@ -1949,7 +1996,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19491996 if (compiler_rt_strat == .zcu) {
19501997 // For objects, this mechanism relies on essentially `_ = @import("compiler-rt");`
19511998 // injected into the object.
1952 const compiler_rt_mod = try Package.Module.create(arena, .{
1999 const compiler_rt_mod = Package.Module.create(arena, .{
19532000 .paths = .{
19542001 .root = .zig_lib_root,
19552002 .root_src_path = "compiler_rt.zig",
......@@ -1963,7 +2010,22 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19632010 },
19642011 .global = options.config,
19652012 .parent = options.root_mod,
1966 });
2013 }) catch |err| switch (err) {
2014 error.OutOfMemory => |e| return e,
2015 // None of these are possible because the configuration matches the root module
2016 // which already passed these checks.
2017 error.ValgrindUnsupportedOnTarget => unreachable,
2018 error.TargetRequiresSingleThreaded => unreachable,
2019 error.BackendRequiresSingleThreaded => unreachable,
2020 error.TargetRequiresPic => unreachable,
2021 error.PieRequiresPic => unreachable,
2022 error.DynamicLinkingRequiresPic => unreachable,
2023 error.TargetHasNoRedZone => unreachable,
2024 // These are not possible because are explicitly *not* requesting these things.
2025 error.StackCheckUnsupportedByTarget => unreachable,
2026 error.StackProtectorUnsupportedByTarget => unreachable,
2027 error.StackProtectorUnavailableWithoutLibC => unreachable,
2028 };
19672029 try options.root_mod.deps.putNoClobber(arena, "compiler_rt", compiler_rt_mod);
19682030 }
19692031
......@@ -1981,7 +2043,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19812043 };
19822044
19832045 if (ubsan_rt_strat == .zcu) {
1984 const ubsan_rt_mod = try Package.Module.create(arena, .{
2046 const ubsan_rt_mod = Package.Module.create(arena, .{
19852047 .paths = .{
19862048 .root = .zig_lib_root,
19872049 .root_src_path = "ubsan_rt.zig",
......@@ -1991,7 +2053,21 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
19912053 .inherited = .{},
19922054 .global = options.config,
19932055 .parent = options.root_mod,
1994 });
2056 }) catch |err| switch (err) {
2057 error.OutOfMemory => |e| return e,
2058 // None of these are possible because the configuration matches the root module
2059 // which already passed these checks.
2060 error.ValgrindUnsupportedOnTarget => unreachable,
2061 error.TargetRequiresSingleThreaded => unreachable,
2062 error.BackendRequiresSingleThreaded => unreachable,
2063 error.TargetRequiresPic => unreachable,
2064 error.PieRequiresPic => unreachable,
2065 error.DynamicLinkingRequiresPic => unreachable,
2066 error.TargetHasNoRedZone => unreachable,
2067 error.StackCheckUnsupportedByTarget => unreachable,
2068 error.StackProtectorUnsupportedByTarget => unreachable,
2069 error.StackProtectorUnavailableWithoutLibC => unreachable,
2070 };
19952071 try options.root_mod.deps.putNoClobber(arena, "ubsan_rt", ubsan_rt_mod);
19962072 }
19972073
......@@ -2019,7 +2095,9 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
20192095 const cache = try arena.create(Cache);
20202096 cache.* = .{
20212097 .gpa = gpa,
2022 .manifest_dir = try options.dirs.local_cache.handle.makeOpenPath("h", .{}),
2098 .manifest_dir = options.dirs.local_cache.handle.makeOpenPath("h", .{}) catch |err| {
2099 return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = "h", .err = err } });
2100 },
20232101 };
20242102 // These correspond to std.zig.Server.Message.PathPrefix.
20252103 cache.addPrefix(.{ .path = null, .handle = fs.cwd() });
......@@ -2067,20 +2145,24 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
20672145 // to redundantly happen for each AstGen operation.
20682146 const zir_sub_dir = "z";
20692147
2070 var local_zir_dir = try options.dirs.local_cache.handle.makeOpenPath(zir_sub_dir, .{});
2148 var local_zir_dir = options.dirs.local_cache.handle.makeOpenPath(zir_sub_dir, .{}) catch |err| {
2149 return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = zir_sub_dir, .err = err } });
2150 };
20712151 errdefer local_zir_dir.close();
20722152 const local_zir_cache: Cache.Directory = .{
20732153 .handle = local_zir_dir,
20742154 .path = try options.dirs.local_cache.join(arena, &.{zir_sub_dir}),
20752155 };
2076 var global_zir_dir = try options.dirs.global_cache.handle.makeOpenPath(zir_sub_dir, .{});
2156 var global_zir_dir = options.dirs.global_cache.handle.makeOpenPath(zir_sub_dir, .{}) catch |err| {
2157 return diag.fail(.{ .create_cache_path = .{ .which = .global, .sub = zir_sub_dir, .err = err } });
2158 };
20772159 errdefer global_zir_dir.close();
20782160 const global_zir_cache: Cache.Directory = .{
20792161 .handle = global_zir_dir,
20802162 .path = try options.dirs.global_cache.join(arena, &.{zir_sub_dir}),
20812163 };
20822164
2083 const std_mod = options.std_mod orelse try Package.Module.create(arena, .{
2165 const std_mod = options.std_mod orelse Package.Module.create(arena, .{
20842166 .paths = .{
20852167 .root = try .fromRoot(arena, options.dirs, .zig_lib, "std"),
20862168 .root_src_path = "std.zig",
......@@ -2090,7 +2172,21 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
20902172 .inherited = .{},
20912173 .global = options.config,
20922174 .parent = options.root_mod,
2093 });
2175 }) catch |err| return switch (err) {
2176 error.OutOfMemory => |e| return e,
2177 // None of these are possible because the configuration matches the root module
2178 // which already passed these checks.
2179 error.ValgrindUnsupportedOnTarget => unreachable,
2180 error.TargetRequiresSingleThreaded => unreachable,
2181 error.BackendRequiresSingleThreaded => unreachable,
2182 error.TargetRequiresPic => unreachable,
2183 error.PieRequiresPic => unreachable,
2184 error.DynamicLinkingRequiresPic => unreachable,
2185 error.TargetHasNoRedZone => unreachable,
2186 error.StackCheckUnsupportedByTarget => unreachable,
2187 error.StackProtectorUnsupportedByTarget => unreachable,
2188 error.StackProtectorUnavailableWithoutLibC => unreachable,
2189 };
20942190
20952191 const zcu = try arena.create(Zcu);
20962192 zcu.* = .{
......@@ -2109,7 +2205,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
21092205 try zcu.init(options.thread_pool.getIdCount());
21102206 break :blk zcu;
21112207 } else blk: {
2112 if (options.emit_h != .no) return error.NoZigModuleForCHeader;
2208 if (options.emit_h != .no) return diag.fail(.emit_h_without_zcu);
21132209 break :blk null;
21142210 };
21152211 errdefer if (opt_zcu) |zcu| zcu.deinit();
......@@ -2204,7 +2300,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
22042300 // Populate `zcu.module_roots`.
22052301 const pt: Zcu.PerThread = .activate(zcu, .main);
22062302 defer pt.deactivate();
2207 try pt.populateModuleRootTable();
2303 pt.populateModuleRootTable() catch |err| switch (err) {
2304 error.OutOfMemory => |e| return e,
2305 error.IllegalZigImport => return diag.fail(.illegal_zig_import),
2306 };
22082307 }
22092308
22102309 const lf_open_opts: link.File.OpenOptions = .{
......@@ -2279,10 +2378,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
22792378 none.* = .{ .tmp_artifact_directory = null };
22802379 comp.cache_use = .{ .none = none };
22812380 if (comp.emit_bin) |path| {
2282 comp.bin_file = try link.File.open(arena, comp, .{
2381 comp.bin_file = link.File.open(arena, comp, .{
22832382 .root_dir = .cwd(),
22842383 .sub_path = path,
2285 }, lf_open_opts);
2384 }, lf_open_opts) catch |err| {
2385 return diag.fail(.{ .open_output_bin = err });
2386 };
22862387 }
22872388 },
22882389 .incremental => {
......@@ -2320,7 +2421,9 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
23202421 const digest = hash.final();
23212422
23222423 const artifact_sub_dir = "o" ++ fs.path.sep_str ++ digest;
2323 var artifact_dir = try options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{});
2424 var artifact_dir = options.dirs.local_cache.handle.makeOpenPath(artifact_sub_dir, .{}) catch |err| {
2425 return diag.fail(.{ .create_cache_path = .{ .which = .local, .sub = artifact_sub_dir, .err = err } });
2426 };
23242427 errdefer artifact_dir.close();
23252428 const artifact_directory: Cache.Directory = .{
23262429 .handle = artifact_dir,
......@@ -2338,7 +2441,9 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
23382441 .root_dir = artifact_directory,
23392442 .sub_path = cache_rel_path,
23402443 };
2341 comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts);
2444 comp.bin_file = link.File.open(arena, comp, emit, lf_open_opts) catch |err| {
2445 return diag.fail(.{ .open_output_bin = err });
2446 };
23422447 }
23432448 },
23442449 .whole => {
......@@ -2433,7 +2538,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24332538 .link_mode = comp.config.link_mode,
24342539 .pie = comp.config.pie,
24352540 });
2436 const paths = try lci.resolveCrtPaths(arena, basenames, target);
2541 const paths = lci.resolveCrtPaths(arena, basenames, target) catch |err| switch (err) {
2542 error.OutOfMemory => |e| return e,
2543 error.LibCInstallationMissingCrtDir => return diag.fail(.libc_installation_missing_crt_dir),
2544 };
24372545
24382546 const fields = @typeInfo(@TypeOf(paths)).@"struct".fields;
24392547 try comp.link_task_queue.queued_prelink.ensureUnusedCapacity(gpa, fields.len + 1);
......@@ -2445,7 +2553,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24452553 // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`.
24462554 comp.link_task_queue.queued_prelink.appendAssumeCapacity(.load_host_libc);
24472555 } else if (target.isMuslLibC()) {
2448 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
2556 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);
24492557
24502558 if (musl.needsCrt0(comp.config.output_mode, comp.config.link_mode, comp.config.pie)) |f| {
24512559 comp.queued_jobs.musl_crt_file[@intFromEnum(f)] = true;
......@@ -2455,7 +2563,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24552563 .dynamic => comp.queued_jobs.musl_crt_file[@intFromEnum(musl.CrtFile.libc_so)] = true,
24562564 }
24572565 } else if (target.isGnuLibC()) {
2458 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
2566 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);
24592567
24602568 if (glibc.needsCrt0(comp.config.output_mode)) |f| {
24612569 comp.queued_jobs.glibc_crt_file[@intFromEnum(f)] = true;
......@@ -2464,7 +2572,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24642572
24652573 comp.queued_jobs.glibc_crt_file[@intFromEnum(glibc.CrtFile.libc_nonshared_a)] = true;
24662574 } else if (target.isFreeBSDLibC()) {
2467 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
2575 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);
24682576
24692577 if (freebsd.needsCrt0(comp.config.output_mode)) |f| {
24702578 comp.queued_jobs.freebsd_crt_file[@intFromEnum(f)] = true;
......@@ -2472,7 +2580,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24722580
24732581 comp.queued_jobs.freebsd_shared_objects = true;
24742582 } else if (target.isNetBSDLibC()) {
2475 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
2583 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);
24762584
24772585 if (netbsd.needsCrt0(comp.config.output_mode)) |f| {
24782586 comp.queued_jobs.netbsd_crt_file[@intFromEnum(f)] = true;
......@@ -2480,12 +2588,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24802588
24812589 comp.queued_jobs.netbsd_shared_objects = true;
24822590 } else if (target.isWasiLibC()) {
2483 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
2591 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);
24842592
24852593 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.execModelCrtFile(comp.config.wasi_exec_model))] = true;
24862594 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.CrtFile.libc_a)] = true;
24872595 } else if (target.isMinGW()) {
2488 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
2596 if (!std.zig.target.canBuildLibC(target)) return diag.fail(.cross_libc_unavailable);
24892597
24902598 const main_crt_file: mingw.CrtFile = if (is_dyn_lib) .dllcrt2_o else .crt2_o;
24912599 comp.queued_jobs.mingw_crt_file[@intFromEnum(main_crt_file)] = true;
......@@ -2495,7 +2603,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
24952603 try comp.windows_libs.ensureUnusedCapacity(gpa, mingw.always_link_libs.len);
24962604 for (mingw.always_link_libs) |name| comp.windows_libs.putAssumeCapacity(try gpa.dupe(u8, name), {});
24972605 } else {
2498 return error.LibCUnavailable;
2606 return diag.fail(.cross_libc_unavailable);
24992607 }
25002608
25012609 if ((target.isMuslLibC() and comp.config.link_mode == .static) or
......@@ -2737,8 +2845,14 @@ fn cleanupAfterUpdate(comp: *Compilation, tmp_dir_rand_int: u64) void {
27372845 }
27382846}
27392847
2848pub const UpdateError = error{
2849 OutOfMemory,
2850 Unexpected,
2851 CurrentWorkingDirectoryUnlinked,
2852};
2853
27402854/// Detect changes to source files, perform semantic analysis, and update the output files.
2741pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
2855pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateError!void {
27422856 const tracy_trace = trace(@src());
27432857 defer tracy_trace.end();
27442858
......@@ -2769,10 +2883,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
27692883 tmp_dir_rand_int = std.crypto.random.int(u64);
27702884 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
27712885 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
2772 break :d .{
2773 .path = path,
2774 .handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}),
2886 const handle = comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}) catch |err| {
2887 return comp.setMiscFailure(.open_output, "failed to create output directory '{s}': {t}", .{ path, err });
27752888 };
2889 break :d .{ .path = path, .handle = handle };
27762890 };
27772891 },
27782892 .incremental => {},
......@@ -2849,17 +2963,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
28492963 tmp_dir_rand_int = std.crypto.random.int(u64);
28502964 const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(tmp_dir_rand_int);
28512965 const path = try comp.dirs.local_cache.join(arena, &.{tmp_dir_sub_path});
2852 break :d .{
2853 .path = path,
2854 .handle = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}),
2966 const handle = comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}) catch |err| {
2967 return comp.setMiscFailure(.open_output, "failed to create output directory '{s}': {t}", .{ path, err });
28552968 };
2969 break :d .{ .path = path, .handle = handle };
28562970 };
28572971 if (comp.emit_bin) |sub_path| {
28582972 const emit: Cache.Path = .{
28592973 .root_dir = whole.tmp_artifact_directory.?,
28602974 .sub_path = sub_path,
28612975 };
2862 comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts);
2976 comp.bin_file = link.File.createEmpty(arena, comp, emit, whole.lf_open_opts) catch |err| {
2977 return comp.setMiscFailure(.open_output, "failed to open output file '{f}': {t}", .{ emit, err });
2978 };
28632979 }
28642980 },
28652981 }
......@@ -3036,11 +3152,11 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
30363152 renameTmpIntoCache(comp.dirs.local_cache, tmp_dir_sub_path, o_sub_path) catch |err| {
30373153 return comp.setMiscFailure(
30383154 .rename_results,
3039 "failed to rename compilation results ('{f}{s}') into local cache ('{f}{s}'): {s}",
3155 "failed to rename compilation results ('{f}{s}') into local cache ('{f}{s}'): {t}",
30403156 .{
30413157 comp.dirs.local_cache, tmp_dir_sub_path,
30423158 comp.dirs.local_cache, o_sub_path,
3043 @errorName(err),
3159 err,
30443160 },
30453161 );
30463162 };
......@@ -3054,15 +3170,21 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
30543170 .root_dir = comp.dirs.local_cache,
30553171 .sub_path = try fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
30563172 };
3057
3058 switch (need_writable_dance) {
3173 const result: link.File.OpenError!void = switch (need_writable_dance) {
30593174 .no => {},
3060 .lf_only => try lf.makeWritable(),
3061 .lf_and_debug => {
3062 try lf.makeWritable();
3063 try lf.reopenDebugInfo();
3175 .lf_only => lf.makeWritable(),
3176 .lf_and_debug => res: {
3177 lf.makeWritable() catch |err| break :res err;
3178 lf.reopenDebugInfo() catch |err| break :res err;
30643179 },
3065 }
3180 };
3181 result catch |err| {
3182 return comp.setMiscFailure(
3183 .rename_results,
3184 "failed to re-open renamed compilation results ('{f}{s}'): {t}",
3185 .{ comp.dirs.local_cache, o_sub_path, err },
3186 );
3187 };
30663188 }
30673189
30683190 try flush(comp, arena, .main);
......@@ -3155,7 +3277,7 @@ fn flush(
31553277 comp: *Compilation,
31563278 arena: Allocator,
31573279 tid: Zcu.PerThread.Id,
3158) !void {
3280) Allocator.Error!void {
31593281 if (comp.zcu) |zcu| {
31603282 if (zcu.llvm_object) |llvm_object| {
31613283 const pt: Zcu.PerThread = .activate(zcu, tid);
......@@ -3173,7 +3295,7 @@ fn flush(
31733295 comp.time_report.?.stats.real_ns_llvm_emit = ns;
31743296 };
31753297
3176 try llvm_object.emit(pt, .{
3298 llvm_object.emit(pt, .{
31773299 .pre_ir_path = comp.verbose_llvm_ir,
31783300 .pre_bc_path = comp.verbose_llvm_bc,
31793301
......@@ -3204,7 +3326,10 @@ fn flush(
32043326 .sanitize_thread = comp.config.any_sanitize_thread,
32053327 .fuzz = comp.config.any_fuzz,
32063328 .lto = comp.config.lto,
3207 });
3329 }) catch |err| switch (err) {
3330 error.LinkFailure => {}, // Already reported.
3331 error.OutOfMemory => return error.OutOfMemory,
3332 };
32083333 }
32093334 }
32103335 if (comp.bin_file) |lf| {
......@@ -3746,7 +3871,7 @@ fn addBuf(list: *std.ArrayList([]const u8), buf: []const u8) void {
37463871}
37473872
37483873/// This function is temporally single-threaded.
3749pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3874pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
37503875 const gpa = comp.gpa;
37513876
37523877 var bundle: ErrorBundle.Wip = undefined;
......@@ -3796,8 +3921,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
37963921 for (zcu.failed_imports.items) |failed| {
37973922 assert(zcu.alive_files.contains(failed.file_index)); // otherwise it wouldn't have been added
37983923 const file = zcu.fileByIndex(failed.file_index);
3799 const source = try file.getSource(zcu);
3800 const tree = try file.getTree(zcu);
3924 const source = file.getSource(zcu) catch |err| {
3925 try unableToLoadZcuFile(zcu, &bundle, file, err);
3926 continue;
3927 };
3928 const tree = file.getTree(zcu) catch |err| {
3929 try unableToLoadZcuFile(zcu, &bundle, file, err);
3930 continue;
3931 };
38013932 const start = tree.tokenStart(failed.import_token);
38023933 const end = start + tree.tokenSlice(failed.import_token).len;
38033934 const loc = std.zig.findLineColumn(source.bytes, start);
......@@ -3853,7 +3984,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
38533984 } else {
38543985 assert(!is_retryable);
38553986 // AstGen/ZoirGen succeeded with errors. Note that this may include AST errors.
3856 _ = try file.getTree(zcu); // Tree must be loaded.
3987 // Tree must be loaded.
3988 _ = file.getTree(zcu) catch |err| {
3989 try unableToLoadZcuFile(zcu, &bundle, file, err);
3990 continue;
3991 };
38573992 const path = try std.fmt.allocPrint(gpa, "{f}", .{file.path.fmt(comp)});
38583993 defer gpa.free(path);
38593994 if (file.zir != null) {
......@@ -3871,16 +4006,19 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
38714006 const SortOrder = struct {
38724007 zcu: *Zcu,
38734008 errors: []const *Zcu.ErrorMsg,
3874 err: *?Error,
3875
3876 const Error = @typeInfo(
3877 @typeInfo(@TypeOf(Zcu.LazySrcLoc.lessThan)).@"fn".return_type.?,
3878 ).error_union.error_set;
3879
4009 read_err: *?ReadError,
4010 const ReadError = struct {
4011 file: *Zcu.File,
4012 err: Zcu.File.GetSourceError,
4013 };
38804014 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
3881 if (ctx.err.* != null) return lhs_index < rhs_index;
3882 return ctx.errors[lhs_index].src_loc.lessThan(ctx.errors[rhs_index].src_loc, ctx.zcu) catch |e| {
3883 ctx.err.* = e;
4015 if (ctx.read_err.* != null) return lhs_index < rhs_index;
4016 var bad_file: *Zcu.File = undefined;
4017 return ctx.errors[lhs_index].src_loc.lessThan(ctx.errors[rhs_index].src_loc, ctx.zcu, &bad_file) catch |err| {
4018 ctx.read_err.* = .{
4019 .file = bad_file,
4020 .err = err,
4021 };
38844022 return lhs_index < rhs_index;
38854023 };
38864024 }
......@@ -3892,13 +4030,16 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
38924030 var entries = try zcu.failed_analysis.entries.clone(gpa);
38934031 errdefer entries.deinit(gpa);
38944032
3895 var err: ?SortOrder.Error = null;
4033 var read_err: ?SortOrder.ReadError = null;
38964034 entries.sort(SortOrder{
38974035 .zcu = zcu,
38984036 .errors = entries.items(.value),
3899 .err = &err,
4037 .read_err = &read_err,
39004038 });
3901 if (err) |e| return e;
4039 if (read_err) |e| {
4040 try unableToLoadZcuFile(zcu, &bundle, e.file, e.err);
4041 break :zcu_errors;
4042 }
39024043 break :s entries.slice();
39034044 };
39044045 defer sorted_failed_analysis.deinit(gpa);
......@@ -4018,23 +4159,33 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
40184159
40194160 // Okay, there *are* referenced compile logs. Sort them into a consistent order.
40204161
4021 const SortContext = struct {
4022 err: *?Error,
4023 zcu: *Zcu,
4024 const Error = @typeInfo(
4025 @typeInfo(@TypeOf(Zcu.LazySrcLoc.lessThan)).@"fn".return_type.?,
4026 ).error_union.error_set;
4027 fn lessThan(ctx: @This(), lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool {
4028 if (ctx.err.* != null) return false;
4029 return lhs.src_loc.lessThan(rhs.src_loc, ctx.zcu) catch |e| {
4030 ctx.err.* = e;
4031 return false;
4162 {
4163 const SortContext = struct {
4164 zcu: *Zcu,
4165 read_err: *?ReadError,
4166 const ReadError = struct {
4167 file: *Zcu.File,
4168 err: Zcu.File.GetSourceError,
40324169 };
4170 fn lessThan(ctx: @This(), lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool {
4171 if (ctx.read_err.* != null) return false;
4172 var bad_file: *Zcu.File = undefined;
4173 return lhs.src_loc.lessThan(rhs.src_loc, ctx.zcu, &bad_file) catch |err| {
4174 ctx.read_err.* = .{
4175 .file = bad_file,
4176 .err = err,
4177 };
4178 return false;
4179 };
4180 }
4181 };
4182 var read_err: ?SortContext.ReadError = null;
4183 std.mem.sort(Zcu.ErrorMsg, messages.items, @as(SortContext, .{ .read_err = &read_err, .zcu = zcu }), SortContext.lessThan);
4184 if (read_err) |e| {
4185 try unableToLoadZcuFile(zcu, &bundle, e.file, e.err);
4186 break :compile_log_text "";
40334187 }
4034 };
4035 var sort_err: ?SortContext.Error = null;
4036 std.mem.sort(Zcu.ErrorMsg, messages.items, @as(SortContext, .{ .err = &sort_err, .zcu = zcu }), SortContext.lessThan);
4037 if (sort_err) |e| return e;
4188 }
40384189
40394190 var log_text: std.ArrayListUnmanaged(u8) = .empty;
40404191 defer log_text.deinit(gpa);
......@@ -4068,18 +4219,19 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
40684219 // This AU is referenced and has a transitive compile error, meaning it referenced something with a compile error.
40694220 // However, we haven't reported any such error.
40704221 // This is a compiler bug.
4071 var stderr_w = std.debug.lockStderrWriter(&.{});
4072 defer std.debug.unlockStderrWriter();
4073 try stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n");
4074 try stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)});
4075 while (ref) |r| {
4076 try stderr_w.print("referenced by: {f}{s}\n", .{
4077 zcu.fmtAnalUnit(r.referencer),
4078 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
4079 });
4080 ref = refs.get(r.referencer).?;
4222 print_ctx: {
4223 var stderr_w = std.debug.lockStderrWriter(&.{});
4224 defer std.debug.unlockStderrWriter();
4225 stderr_w.writeAll("referenced transitive analysis errors, but none actually emitted\n") catch break :print_ctx;
4226 stderr_w.print("{f} [transitive failure]\n", .{zcu.fmtAnalUnit(failed_unit)}) catch break :print_ctx;
4227 while (ref) |r| {
4228 stderr_w.print("referenced by: {f}{s}\n", .{
4229 zcu.fmtAnalUnit(r.referencer),
4230 if (zcu.transitive_failed_analysis.contains(r.referencer)) " [transitive failure]" else "",
4231 }) catch break :print_ctx;
4232 ref = refs.get(r.referencer).?;
4233 }
40814234 }
4082
40834235 @panic("referenced transitive analysis errors, but none actually emitted");
40844236 }
40854237 };
......@@ -4166,19 +4318,16 @@ pub fn addModuleErrorMsg(
41664318 /// If `-freference-trace` is not specified, we only want to show the one reference trace.
41674319 /// So, this is whether we have already emitted an error with a reference trace.
41684320 already_added_error: bool,
4169) !void {
4321) Allocator.Error!void {
41704322 const gpa = eb.gpa;
41714323 const ip = &zcu.intern_pool;
41724324 const err_src_loc = module_err_msg.src_loc.upgrade(zcu);
41734325 const err_source = err_src_loc.file_scope.getSource(zcu) catch |err| {
4174 try eb.addRootErrorMessage(.{
4175 .msg = try eb.printString("unable to load '{f}': {s}", .{
4176 err_src_loc.file_scope.path.fmt(zcu.comp), @errorName(err),
4177 }),
4178 });
4179 return;
4326 return unableToLoadZcuFile(zcu, eb, err_src_loc.file_scope, err);
4327 };
4328 const err_span = err_src_loc.span(zcu) catch |err| {
4329 return unableToLoadZcuFile(zcu, eb, err_src_loc.file_scope, err);
41804330 };
4181 const err_span = try err_src_loc.span(zcu);
41824331 const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.main);
41834332
41844333 var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .empty;
......@@ -4208,7 +4357,13 @@ pub fn addModuleErrorMsg(
42084357 const f = inline_frame.ptr(zcu).*;
42094358 const func_nav = ip.indexToKey(f.callee).func.owner_nav;
42104359 const func_name = ip.getNav(func_nav).name.toSlice(ip);
4211 try addReferenceTraceFrame(zcu, eb, &ref_traces, func_name, last_call_src, true);
4360 addReferenceTraceFrame(zcu, eb, &ref_traces, func_name, last_call_src, true) catch |err| switch (err) {
4361 error.OutOfMemory => |e| return e,
4362 error.AlreadyReported => {
4363 // An incomplete reference trace isn't the end of the world; just cut it off.
4364 break :rt;
4365 },
4366 };
42124367 last_call_src = f.call_src;
42134368 opt_inline_frame = f.parent;
42144369 }
......@@ -4220,7 +4375,13 @@ pub fn addModuleErrorMsg(
42204375 .memoized_state => null,
42214376 };
42224377 if (root_name) |n| {
4223 try addReferenceTraceFrame(zcu, eb, &ref_traces, n, last_call_src, false);
4378 addReferenceTraceFrame(zcu, eb, &ref_traces, n, last_call_src, false) catch |err| switch (err) {
4379 error.OutOfMemory => |e| return e,
4380 error.AlreadyReported => {
4381 // An incomplete reference trace isn't the end of the world; just cut it off.
4382 break :rt;
4383 },
4384 };
42244385 }
42254386 }
42264387 referenced_by = ref.referencer;
......@@ -4257,8 +4418,12 @@ pub fn addModuleErrorMsg(
42574418 var last_note_loc: ?std.zig.Loc = null;
42584419 for (module_err_msg.notes) |module_note| {
42594420 const note_src_loc = module_note.src_loc.upgrade(zcu);
4260 const source = try note_src_loc.file_scope.getSource(zcu);
4261 const span = try note_src_loc.span(zcu);
4421 const source = note_src_loc.file_scope.getSource(zcu) catch |err| {
4422 return unableToLoadZcuFile(zcu, eb, note_src_loc.file_scope, err);
4423 };
4424 const span = note_src_loc.span(zcu) catch |err| {
4425 return unableToLoadZcuFile(zcu, eb, note_src_loc.file_scope, err);
4426 };
42624427 const loc = std.zig.findLineColumn(source.bytes, span.main);
42634428
42644429 const omit_source_line = loc.eql(err_loc) or (last_note_loc != null and loc.eql(last_note_loc.?));
......@@ -4303,11 +4468,17 @@ fn addReferenceTraceFrame(
43034468 name: []const u8,
43044469 lazy_src: Zcu.LazySrcLoc,
43054470 inlined: bool,
4306) !void {
4471) error{ OutOfMemory, AlreadyReported }!void {
43074472 const gpa = zcu.gpa;
43084473 const src = lazy_src.upgrade(zcu);
4309 const source = try src.file_scope.getSource(zcu);
4310 const span = try src.span(zcu);
4474 const source = src.file_scope.getSource(zcu) catch |err| {
4475 try unableToLoadZcuFile(zcu, eb, src.file_scope, err);
4476 return error.AlreadyReported;
4477 };
4478 const span = src.span(zcu) catch |err| {
4479 try unableToLoadZcuFile(zcu, eb, src.file_scope, err);
4480 return error.AlreadyReported;
4481 };
43114482 const loc = std.zig.findLineColumn(source.bytes, span.main);
43124483 try ref_traces.append(gpa, .{
43134484 .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }),
......@@ -4323,19 +4494,26 @@ fn addReferenceTraceFrame(
43234494 });
43244495}
43254496
4326pub fn addWholeFileError(
4497fn addWholeFileError(
43274498 zcu: *Zcu,
43284499 eb: *ErrorBundle.Wip,
43294500 file_index: Zcu.File.Index,
43304501 msg: []const u8,
4331) !void {
4502) Allocator.Error!void {
43324503 // note: "file imported here" on the import reference token
43334504 const imported_note: ?ErrorBundle.MessageIndex = switch (zcu.alive_files.get(file_index).?) {
43344505 .analysis_root => null,
4335 .import => |import| try eb.addErrorMessage(.{
4336 .msg = try eb.addString("file imported here"),
4337 .src_loc = try zcu.fileByIndex(import.importer).errorBundleTokenSrc(import.tok, zcu, eb),
4338 }),
4506 .import => |import| note: {
4507 const file = zcu.fileByIndex(import.importer);
4508 // `errorBundleTokenSrc` expects the tree to be loaded
4509 _ = file.getTree(zcu) catch |err| {
4510 return unableToLoadZcuFile(zcu, eb, file, err);
4511 };
4512 break :note try eb.addErrorMessage(.{
4513 .msg = try eb.addString("file imported here"),
4514 .src_loc = try file.errorBundleTokenSrc(import.tok, zcu, eb),
4515 });
4516 },
43394517 };
43404518
43414519 try eb.addRootErrorMessage(.{
......@@ -4349,6 +4527,20 @@ pub fn addWholeFileError(
43494527 }
43504528}
43514529
4530/// Adds an error to `eb` that the contents of `file` could not be loaded due to `err`. This is
4531/// useful if `Zcu.File.getSource`/`Zcu.File.getTree` fails while lowering compile errors.
4532pub fn unableToLoadZcuFile(
4533 zcu: *const Zcu,
4534 eb: *ErrorBundle.Wip,
4535 file: *Zcu.File,
4536 err: Zcu.File.GetSourceError,
4537) Allocator.Error!void {
4538 try eb.addRootErrorMessage(.{
4539 .msg = try eb.printString("unable to load: {t}", .{err}),
4540 .src_loc = try file.errorBundleWholeFileSrc(zcu, eb),
4541 });
4542}
4543
43524544fn performAllTheWork(
43534545 comp: *Compilation,
43544546 main_progress_node: std.Progress.Node,
......@@ -5002,18 +5194,15 @@ pub fn separateCodegenThreadOk(comp: *const Compilation) bool {
50025194}
50035195
50045196fn workerDocsCopy(comp: *Compilation) void {
5005 docsCopyFallible(comp) catch |err| {
5006 return comp.lockAndSetMiscFailure(
5007 .docs_copy,
5008 "unable to copy autodocs artifacts: {s}",
5009 .{@errorName(err)},
5010 );
5011 };
5197 docsCopyFallible(comp) catch |err| return comp.lockAndSetMiscFailure(
5198 .docs_copy,
5199 "unable to copy autodocs artifacts: {s}",
5200 .{@errorName(err)},
5201 );
50125202}
50135203
50145204fn docsCopyFallible(comp: *Compilation) anyerror!void {
5015 const zcu = comp.zcu orelse
5016 return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{});
5205 const zcu = comp.zcu orelse return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{});
50175206
50185207 const docs_path = comp.resolveEmitPath(comp.emit_docs.?);
50195208 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
......@@ -5127,12 +5316,12 @@ fn workerDocsWasm(comp: *Compilation, parent_prog_node: std.Progress.Node) void
51275316 defer prog_node.end();
51285317
51295318 workerDocsWasmFallible(comp, prog_node) catch |err| switch (err) {
5130 error.SubCompilationFailed => return, // error reported already
5319 error.AlreadyReported => return,
51315320 else => comp.lockAndSetMiscFailure(.docs_wasm, "unable to build autodocs: {t}", .{err}),
51325321 };
51335322}
51345323
5135fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anyerror!void {
5324fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubUpdateError!void {
51365325 const gpa = comp.gpa;
51375326
51385327 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
......@@ -5162,7 +5351,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
51625351 .is_explicit_dynamic_linker = false,
51635352 };
51645353
5165 const config = try Config.resolve(.{
5354 const config = Config.resolve(.{
51665355 .output_mode = output_mode,
51675356 .resolved_target = resolved_target,
51685357 .is_test = false,
......@@ -5171,14 +5360,17 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
51715360 .root_optimize_mode = optimize_mode,
51725361 .link_libc = false,
51735362 .rdynamic = true,
5174 });
5363 }) catch |err| {
5364 comp.lockAndSetMiscFailure(.docs_wasm, "sub-compilation of docs_wasm failed: failed to resolve compilation config: {t}", .{err});
5365 return error.AlreadyReported;
5366 };
51755367
51765368 const src_basename = "main.zig";
51775369 const root_name = fs.path.stem(src_basename);
51785370
51795371 const dirs = comp.dirs.withoutLocalCache();
51805372
5181 const root_mod = try Package.Module.create(arena, .{
5373 const root_mod = Package.Module.create(arena, .{
51825374 .paths = .{
51835375 .root = try .fromRoot(arena, dirs, .zig_lib, "docs/wasm"),
51845376 .root_src_path = src_basename,
......@@ -5191,8 +5383,11 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
51915383 .global = config,
51925384 .cc_argv = &.{},
51935385 .parent = null,
5194 });
5195 const walk_mod = try Package.Module.create(arena, .{
5386 }) catch |err| {
5387 comp.lockAndSetMiscFailure(.docs_wasm, "sub-compilation of docs_wasm failed: failed to create root module: {t}", .{err});
5388 return error.AlreadyReported;
5389 };
5390 const walk_mod = Package.Module.create(arena, .{
51965391 .paths = .{
51975392 .root = try .fromRoot(arena, dirs, .zig_lib, "docs/wasm"),
51985393 .root_src_path = "Walk.zig",
......@@ -5205,10 +5400,14 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
52055400 .global = config,
52065401 .cc_argv = &.{},
52075402 .parent = root_mod,
5208 });
5403 }) catch |err| {
5404 comp.lockAndSetMiscFailure(.docs_wasm, "sub-compilation of docs_wasm failed: failed to create 'Walk' module: {t}", .{err});
5405 return error.AlreadyReported;
5406 };
52095407 try root_mod.deps.put(arena, "Walk", walk_mod);
52105408
5211 const sub_compilation = try Compilation.create(gpa, arena, .{
5409 var sub_create_diag: CreateDiagnostic = undefined;
5410 const sub_compilation = Compilation.create(gpa, arena, &sub_create_diag, .{
52125411 .dirs = dirs,
52135412 .self_exe_path = comp.self_exe_path,
52145413 .config = config,
......@@ -5228,7 +5427,13 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
52285427 .verbose_llvm_bc = comp.verbose_llvm_bc,
52295428 .verbose_cimport = comp.verbose_cimport,
52305429 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
5231 });
5430 }) catch |err| switch (err) {
5431 error.CreateFail => {
5432 comp.lockAndSetMiscFailure(.docs_wasm, "sub-compilation of docs_wasm failed: {f}", .{sub_create_diag});
5433 return error.AlreadyReported;
5434 },
5435 else => |e| return e,
5436 };
52325437 defer sub_compilation.destroy();
52335438
52345439 try comp.updateSubCompilation(sub_compilation, .docs_wasm, prog_node);
......@@ -5241,11 +5446,12 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
52415446
52425447 const docs_path = comp.resolveEmitPath(comp.emit_docs.?);
52435448 var out_dir = docs_path.root_dir.handle.makeOpenPath(docs_path.sub_path, .{}) catch |err| {
5244 return comp.lockAndSetMiscFailure(
5449 comp.lockAndSetMiscFailure(
52455450 .docs_copy,
5246 "unable to create output directory '{f}': {s}",
5247 .{ docs_path, @errorName(err) },
5451 "unable to create output directory '{f}': {t}",
5452 .{ docs_path, err },
52485453 );
5454 return error.AlreadyReported;
52495455 };
52505456 defer out_dir.close();
52515457
......@@ -5255,9 +5461,10 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
52555461 "main.wasm",
52565462 .{},
52575463 ) catch |err| {
5258 return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{f}' to '{f}': {s}", .{
5259 crt_file.full_object_path, docs_path, @errorName(err),
5464 comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{f}' to '{f}': {t}", .{
5465 crt_file.full_object_path, docs_path, err,
52605466 });
5467 return error.AlreadyReported;
52615468 };
52625469}
52635470
......@@ -5324,15 +5531,11 @@ fn workerUpdateFile(
53245531}
53255532
53265533fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void {
5327 Builtin.updateFileOnDisk(file, comp) catch |err| {
5328 comp.mutex.lock();
5329 defer comp.mutex.unlock();
5330 comp.setMiscFailure(
5331 .write_builtin_zig,
5332 "unable to write '{f}': {s}",
5333 .{ file.path.fmt(comp), @errorName(err) },
5334 );
5335 };
5534 Builtin.updateFileOnDisk(file, comp) catch |err| comp.lockAndSetMiscFailure(
5535 .write_builtin_zig,
5536 "unable to write '{f}': {s}",
5537 .{ file.path.fmt(comp), @errorName(err) },
5538 );
53365539}
53375540
53385541fn workerUpdateEmbedFile(tid: usize, comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void {
......@@ -5632,7 +5835,7 @@ fn buildRt(
56325835 options,
56335836 out,
56345837 ) catch |err| switch (err) {
5635 error.SubCompilationFailed => return, // error reported already
5838 error.AlreadyReported => return,
56365839 else => comp.lockAndSetMiscFailure(misc_task, "unable to build {s}: {s}", .{
56375840 @tagName(misc_task), @errorName(err),
56385841 }),
......@@ -5644,7 +5847,7 @@ fn buildMuslCrtFile(comp: *Compilation, crt_file: musl.CrtFile, prog_node: std.P
56445847 if (musl.buildCrtFile(comp, crt_file, prog_node)) |_| {
56455848 comp.queued_jobs.musl_crt_file[@intFromEnum(crt_file)] = false;
56465849 } else |err| switch (err) {
5647 error.SubCompilationFailed => return, // error reported already
5850 error.AlreadyReported => return,
56485851 else => comp.lockAndSetMiscFailure(.musl_crt_file, "unable to build musl {s}: {s}", .{
56495852 @tagName(crt_file), @errorName(err),
56505853 }),
......@@ -5656,7 +5859,7 @@ fn buildGlibcCrtFile(comp: *Compilation, crt_file: glibc.CrtFile, prog_node: std
56565859 if (glibc.buildCrtFile(comp, crt_file, prog_node)) |_| {
56575860 comp.queued_jobs.glibc_crt_file[@intFromEnum(crt_file)] = false;
56585861 } else |err| switch (err) {
5659 error.SubCompilationFailed => return, // error reported already
5862 error.AlreadyReported => return,
56605863 else => comp.lockAndSetMiscFailure(.glibc_crt_file, "unable to build glibc {s}: {s}", .{
56615864 @tagName(crt_file), @errorName(err),
56625865 }),
......@@ -5669,7 +5872,7 @@ fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) voi
56695872 // The job should no longer be queued up since it succeeded.
56705873 comp.queued_jobs.glibc_shared_objects = false;
56715874 } else |err| switch (err) {
5672 error.SubCompilationFailed => return, // error reported already
5875 error.AlreadyReported => return,
56735876 else => comp.lockAndSetMiscFailure(.glibc_shared_objects, "unable to build glibc shared objects: {s}", .{
56745877 @errorName(err),
56755878 }),
......@@ -5681,7 +5884,7 @@ fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node:
56815884 if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
56825885 comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false;
56835886 } else |err| switch (err) {
5684 error.SubCompilationFailed => return, // error reported already
5887 error.AlreadyReported => return,
56855888 else => comp.lockAndSetMiscFailure(.freebsd_crt_file, "unable to build FreeBSD {s}: {s}", .{
56865889 @tagName(crt_file), @errorName(err),
56875890 }),
......@@ -5694,7 +5897,7 @@ fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) v
56945897 // The job should no longer be queued up since it succeeded.
56955898 comp.queued_jobs.freebsd_shared_objects = false;
56965899 } else |err| switch (err) {
5697 error.SubCompilationFailed => return, // error reported already
5900 error.AlreadyReported => return,
56985901 else => comp.lockAndSetMiscFailure(.freebsd_shared_objects, "unable to build FreeBSD libc shared objects: {s}", .{
56995902 @errorName(err),
57005903 }),
......@@ -5706,7 +5909,7 @@ fn buildNetBSDCrtFile(comp: *Compilation, crt_file: netbsd.CrtFile, prog_node: s
57065909 if (netbsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
57075910 comp.queued_jobs.netbsd_crt_file[@intFromEnum(crt_file)] = false;
57085911 } else |err| switch (err) {
5709 error.SubCompilationFailed => return, // error reported already
5912 error.AlreadyReported => return,
57105913 else => comp.lockAndSetMiscFailure(.netbsd_crt_file, "unable to build NetBSD {s}: {s}", .{
57115914 @tagName(crt_file), @errorName(err),
57125915 }),
......@@ -5719,7 +5922,7 @@ fn buildNetBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) vo
57195922 // The job should no longer be queued up since it succeeded.
57205923 comp.queued_jobs.netbsd_shared_objects = false;
57215924 } else |err| switch (err) {
5722 error.SubCompilationFailed => return, // error reported already
5925 error.AlreadyReported => return,
57235926 else => comp.lockAndSetMiscFailure(.netbsd_shared_objects, "unable to build NetBSD libc shared objects: {s}", .{
57245927 @errorName(err),
57255928 }),
......@@ -5731,7 +5934,7 @@ fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std
57315934 if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| {
57325935 comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false;
57335936 } else |err| switch (err) {
5734 error.SubCompilationFailed => return, // error reported already
5937 error.AlreadyReported => return,
57355938 else => comp.lockAndSetMiscFailure(.mingw_crt_file, "unable to build mingw-w64 {s}: {s}", .{
57365939 @tagName(crt_file), @errorName(err),
57375940 }),
......@@ -5743,7 +5946,7 @@ fn buildWasiLibcCrtFile(comp: *Compilation, crt_file: wasi_libc.CrtFile, prog_no
57435946 if (wasi_libc.buildCrtFile(comp, crt_file, prog_node)) |_| {
57445947 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = false;
57455948 } else |err| switch (err) {
5746 error.SubCompilationFailed => return, // error reported already
5949 error.AlreadyReported => return,
57475950 else => comp.lockAndSetMiscFailure(.wasi_libc_crt_file, "unable to build WASI libc {s}: {s}", .{
57485951 @tagName(crt_file), @errorName(err),
57495952 }),
......@@ -5755,7 +5958,7 @@ fn buildLibUnwind(comp: *Compilation, prog_node: std.Progress.Node) void {
57555958 if (libunwind.buildStaticLib(comp, prog_node)) |_| {
57565959 comp.queued_jobs.libunwind = false;
57575960 } else |err| switch (err) {
5758 error.SubCompilationFailed => return, // error reported already
5961 error.AlreadyReported => return,
57595962 else => comp.lockAndSetMiscFailure(.libunwind, "unable to build libunwind: {s}", .{@errorName(err)}),
57605963 }
57615964}
......@@ -5765,7 +5968,7 @@ fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) void {
57655968 if (libcxx.buildLibCxx(comp, prog_node)) |_| {
57665969 comp.queued_jobs.libcxx = false;
57675970 } else |err| switch (err) {
5768 error.SubCompilationFailed => return, // error reported already
5971 error.AlreadyReported => return,
57695972 else => comp.lockAndSetMiscFailure(.libcxx, "unable to build libcxx: {s}", .{@errorName(err)}),
57705973 }
57715974}
......@@ -5775,7 +5978,7 @@ fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) void {
57755978 if (libcxx.buildLibCxxAbi(comp, prog_node)) |_| {
57765979 comp.queued_jobs.libcxxabi = false;
57775980 } else |err| switch (err) {
5778 error.SubCompilationFailed => return, // error reported already
5981 error.AlreadyReported => return,
57795982 else => comp.lockAndSetMiscFailure(.libcxxabi, "unable to build libcxxabi: {s}", .{@errorName(err)}),
57805983 }
57815984}
......@@ -5785,7 +5988,7 @@ fn buildLibTsan(comp: *Compilation, prog_node: std.Progress.Node) void {
57855988 if (libtsan.buildTsan(comp, prog_node)) |_| {
57865989 comp.queued_jobs.libtsan = false;
57875990 } else |err| switch (err) {
5788 error.SubCompilationFailed => return, // error reported already
5991 error.AlreadyReported => return,
57895992 else => comp.lockAndSetMiscFailure(.libtsan, "unable to build TSAN library: {s}", .{@errorName(err)}),
57905993 }
57915994}
......@@ -5802,7 +6005,7 @@ fn buildLibZigC(comp: *Compilation, prog_node: std.Progress.Node) void {
58026005 .{},
58036006 &comp.zigc_static_lib,
58046007 ) catch |err| switch (err) {
5805 error.SubCompilationFailed => return, // error reported already
6008 error.AlreadyReported => return,
58066009 else => comp.lockAndSetMiscFailure(.libzigc, "unable to build libzigc: {s}", .{@errorName(err)}),
58076010 };
58086011}
......@@ -7439,12 +7642,13 @@ pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {
74397642 return target_util.zigBackend(target, comp.config.use_llvm);
74407643}
74417644
7645pub const SubUpdateError = UpdateError || error{AlreadyReported};
74427646pub fn updateSubCompilation(
74437647 parent_comp: *Compilation,
74447648 sub_comp: *Compilation,
74457649 misc_task: MiscTask,
74467650 prog_node: std.Progress.Node,
7447) !void {
7651) SubUpdateError!void {
74487652 {
74497653 const sub_node = prog_node.start(@tagName(misc_task), 0);
74507654 defer sub_node.end();
......@@ -7454,20 +7658,20 @@ pub fn updateSubCompilation(
74547658
74557659 // Look for compilation errors in this sub compilation
74567660 const gpa = parent_comp.gpa;
7457 var keep_errors = false;
7661
74587662 var errors = try sub_comp.getAllErrorsAlloc();
7459 defer if (!keep_errors) errors.deinit(gpa);
7663 defer errors.deinit(gpa);
74607664
74617665 if (errors.errorMessageCount() > 0) {
7666 parent_comp.mutex.lock();
7667 defer parent_comp.mutex.unlock();
74627668 try parent_comp.misc_failures.ensureUnusedCapacity(gpa, 1);
74637669 parent_comp.misc_failures.putAssumeCapacityNoClobber(misc_task, .{
7464 .msg = try std.fmt.allocPrint(gpa, "sub-compilation of {s} failed", .{
7465 @tagName(misc_task),
7466 }),
7670 .msg = try std.fmt.allocPrint(gpa, "sub-compilation of {t} failed", .{misc_task}),
74677671 .children = errors,
74687672 });
7469 keep_errors = true;
7470 return error.SubCompilationFailed;
7673 errors = .empty; // ownership moved to the failures map
7674 return error.AlreadyReported;
74717675 }
74727676}
74737677
......@@ -7481,7 +7685,7 @@ fn buildOutputFromZig(
74817685 prog_node: std.Progress.Node,
74827686 options: RtOptions,
74837687 out: *?CrtFile,
7484) !void {
7688) SubUpdateError!void {
74857689 const tracy_trace = trace(@src());
74867690 defer tracy_trace.end();
74877691
......@@ -7495,7 +7699,7 @@ fn buildOutputFromZig(
74957699 const strip = comp.compilerRtStrip();
74967700 const optimize_mode = comp.compilerRtOptMode();
74977701
7498 const config = try Config.resolve(.{
7702 const config = Config.resolve(.{
74997703 .output_mode = output_mode,
75007704 .link_mode = link_mode,
75017705 .resolved_target = comp.root_mod.resolved_target,
......@@ -7509,9 +7713,12 @@ fn buildOutputFromZig(
75097713 .any_error_tracing = false,
75107714 .root_error_tracing = false,
75117715 .lto = if (options.allow_lto) comp.config.lto else .none,
7512 });
7716 }) catch |err| {
7717 comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: failed to resolve compilation config: {t}", .{ misc_task_tag, err });
7718 return error.AlreadyReported;
7719 };
75137720
7514 const root_mod = try Package.Module.create(arena, .{
7721 const root_mod = Package.Module.create(arena, .{
75157722 .paths = .{
75167723 .root = .zig_lib_root,
75177724 .root_src_path = src_basename,
......@@ -7536,7 +7743,10 @@ fn buildOutputFromZig(
75367743 .global = config,
75377744 .cc_argv = &.{},
75387745 .parent = null,
7539 });
7746 }) catch |err| {
7747 comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: failed to create module: {t}", .{ misc_task_tag, err });
7748 return error.AlreadyReported;
7749 };
75407750
75417751 const parent_whole_cache: ?ParentWholeCache = switch (comp.cache_use) {
75427752 .whole => |whole| .{
......@@ -7552,7 +7762,8 @@ fn buildOutputFromZig(
75527762 .incremental, .none => null,
75537763 };
75547764
7555 const sub_compilation = try Compilation.create(gpa, arena, .{
7765 var sub_create_diag: CreateDiagnostic = undefined;
7766 const sub_compilation = Compilation.create(gpa, arena, &sub_create_diag, .{
75567767 .dirs = comp.dirs.withoutLocalCache(),
75577768 .cache_mode = .whole,
75587769 .parent_whole_cache = parent_whole_cache,
......@@ -7576,7 +7787,13 @@ fn buildOutputFromZig(
75767787 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
75777788 .clang_passthrough_mode = comp.clang_passthrough_mode,
75787789 .skip_linker_dependencies = true,
7579 });
7790 }) catch |err| switch (err) {
7791 error.CreateFail => {
7792 comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: {f}", .{ misc_task_tag, sub_create_diag });
7793 return error.AlreadyReported;
7794 },
7795 else => |e| return e,
7796 };
75807797 defer sub_compilation.destroy();
75817798
75827799 try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node);
......@@ -7609,7 +7826,7 @@ pub fn build_crt_file(
76097826 /// created within this function.
76107827 c_source_files: []CSourceFile,
76117828 options: CrtFileOptions,
7612) !void {
7829) SubUpdateError!void {
76137830 const tracy_trace = trace(@src());
76147831 defer tracy_trace.end();
76157832
......@@ -7624,7 +7841,7 @@ pub fn build_crt_file(
76247841 .output_mode = output_mode,
76257842 });
76267843
7627 const config = try Config.resolve(.{
7844 const config = Config.resolve(.{
76287845 .output_mode = output_mode,
76297846 .resolved_target = comp.root_mod.resolved_target,
76307847 .is_test = false,
......@@ -7638,8 +7855,11 @@ pub fn build_crt_file(
76387855 .Lib => if (options.allow_lto) comp.config.lto else .none,
76397856 .Obj, .Exe => .none,
76407857 },
7641 });
7642 const root_mod = try Package.Module.create(arena, .{
7858 }) catch |err| {
7859 comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: failed to resolve compilation config: {t}", .{ misc_task_tag, err });
7860 return error.AlreadyReported;
7861 };
7862 const root_mod = Package.Module.create(arena, .{
76437863 .paths = .{
76447864 .root = .zig_lib_root,
76457865 .root_src_path = "",
......@@ -7669,13 +7889,17 @@ pub fn build_crt_file(
76697889 .global = config,
76707890 .cc_argv = &.{},
76717891 .parent = null,
7672 });
7892 }) catch |err| {
7893 comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: failed to create module: {t}", .{ misc_task_tag, err });
7894 return error.AlreadyReported;
7895 };
76737896
76747897 for (c_source_files) |*item| {
76757898 item.owner = root_mod;
76767899 }
76777900
7678 const sub_compilation = try Compilation.create(gpa, arena, .{
7901 var sub_create_diag: CreateDiagnostic = undefined;
7902 const sub_compilation = Compilation.create(gpa, arena, &sub_create_diag, .{
76797903 .dirs = comp.dirs.withoutLocalCache(),
76807904 .self_exe_path = comp.self_exe_path,
76817905 .cache_mode = .whole,
......@@ -7699,7 +7923,13 @@ pub fn build_crt_file(
76997923 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
77007924 .clang_passthrough_mode = comp.clang_passthrough_mode,
77017925 .skip_linker_dependencies = true,
7702 });
7926 }) catch |err| switch (err) {
7927 error.CreateFail => {
7928 comp.lockAndSetMiscFailure(misc_task_tag, "sub-compilation of {t} failed: {f}", .{ misc_task_tag, sub_create_diag });
7929 return error.AlreadyReported;
7930 },
7931 else => |e| return e,
7932 };
77037933 defer sub_compilation.destroy();
77047934
77057935 try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node);
src/Package/Module.zig+14
......@@ -92,6 +92,20 @@ pub const ResolvedTarget = struct {
9292 llvm_cpu_features: ?[*:0]const u8 = null,
9393};
9494
95pub const CreateError = error{
96 OutOfMemory,
97 ValgrindUnsupportedOnTarget,
98 TargetRequiresSingleThreaded,
99 BackendRequiresSingleThreaded,
100 TargetRequiresPic,
101 PieRequiresPic,
102 DynamicLinkingRequiresPic,
103 TargetHasNoRedZone,
104 StackCheckUnsupportedByTarget,
105 StackProtectorUnsupportedByTarget,
106 StackProtectorUnavailableWithoutLibC,
107};
108
95109/// At least one of `parent` and `resolved_target` must be non-null.
96110pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
97111 if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread);
src/Sema.zig+1-2
......@@ -5726,6 +5726,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
57265726 .global = comp.config,
57275727 .parent = parent_mod,
57285728 }) catch |err| switch (err) {
5729 error.OutOfMemory => |e| return e,
57295730 // None of these are possible because we are creating a package with
57305731 // the exact same configuration as the parent package, which already
57315732 // passed these checks.
......@@ -5739,8 +5740,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
57395740 error.StackCheckUnsupportedByTarget => unreachable,
57405741 error.StackProtectorUnsupportedByTarget => unreachable,
57415742 error.StackProtectorUnavailableWithoutLibC => unreachable,
5742
5743 else => |e| return e,
57445743 };
57455744 const c_import_file_path: Compilation.Path = try c_import_mod.root.join(gpa, comp.dirs, "cimport.zig");
57465745 errdefer c_import_file_path.deinit(gpa);
src/Zcu.zig+30-15
......@@ -1038,7 +1038,9 @@ pub const File = struct {
10381038 stat: Cache.File.Stat,
10391039 };
10401040
1041 pub fn getSource(file: *File, zcu: *const Zcu) !Source {
1041 pub const GetSourceError = error{ OutOfMemory, FileTooBig } || std.fs.File.OpenError || std.fs.File.ReadError;
1042
1043 pub fn getSource(file: *File, zcu: *const Zcu) GetSourceError!Source {
10421044 const gpa = zcu.gpa;
10431045
10441046 if (file.source) |source| return .{
......@@ -1062,7 +1064,7 @@ pub const File = struct {
10621064
10631065 var file_reader = f.reader(&.{});
10641066 file_reader.size = stat.size;
1065 try file_reader.interface.readSliceAll(source);
1067 file_reader.interface.readSliceAll(source) catch return file_reader.err.?;
10661068
10671069 // Here we do not modify stat fields because this function is the one
10681070 // used for error reporting. We need to keep the stat fields stale so that
......@@ -1081,7 +1083,7 @@ pub const File = struct {
10811083 };
10821084 }
10831085
1084 pub fn getTree(file: *File, zcu: *const Zcu) !*const Ast {
1086 pub fn getTree(file: *File, zcu: *const Zcu) GetSourceError!*const Ast {
10851087 if (file.tree) |*tree| return tree;
10861088
10871089 const source = try file.getSource(zcu);
......@@ -1127,7 +1129,7 @@ pub const File = struct {
11271129 file: *File,
11281130 zcu: *const Zcu,
11291131 eb: *std.zig.ErrorBundle.Wip,
1130 ) !std.zig.ErrorBundle.SourceLocationIndex {
1132 ) Allocator.Error!std.zig.ErrorBundle.SourceLocationIndex {
11311133 return eb.addSourceLocation(.{
11321134 .src_path = try eb.printString("{f}", .{file.path.fmt(zcu.comp)}),
11331135 .span_start = 0,
......@@ -1138,17 +1140,17 @@ pub const File = struct {
11381140 .source_line = 0,
11391141 });
11401142 }
1143 /// Asserts that the tree has already been loaded with `getTree`.
11411144 pub fn errorBundleTokenSrc(
11421145 file: *File,
11431146 tok: Ast.TokenIndex,
11441147 zcu: *const Zcu,
11451148 eb: *std.zig.ErrorBundle.Wip,
1146 ) !std.zig.ErrorBundle.SourceLocationIndex {
1147 const source = try file.getSource(zcu);
1148 const tree = try file.getTree(zcu);
1149 ) Allocator.Error!std.zig.ErrorBundle.SourceLocationIndex {
1150 const tree = &file.tree.?;
11491151 const start = tree.tokenStart(tok);
11501152 const end = start + tree.tokenSlice(tok).len;
1151 const loc = std.zig.findLineColumn(source.bytes, start);
1153 const loc = std.zig.findLineColumn(file.source.?, start);
11521154 return eb.addSourceLocation(.{
11531155 .src_path = try eb.printString("{f}", .{file.path.fmt(zcu.comp)}),
11541156 .span_start = start,
......@@ -2665,8 +2667,9 @@ pub const LazySrcLoc = struct {
26652667 }
26662668
26672669 /// Used to sort error messages, so that they're printed in a consistent order.
2668 /// If an error is returned, that error makes sorting impossible.
2669 pub fn lessThan(lhs_lazy: LazySrcLoc, rhs_lazy: LazySrcLoc, zcu: *Zcu) !bool {
2670 /// If an error is returned, a file could not be read in order to resolve a source location.
2671 /// In that case, `bad_file_out` is populated, and sorting is impossible.
2672 pub fn lessThan(lhs_lazy: LazySrcLoc, rhs_lazy: LazySrcLoc, zcu: *Zcu, bad_file_out: **Zcu.File) File.GetSourceError!bool {
26702673 const lhs_src = lhs_lazy.upgradeOrLost(zcu) orelse {
26712674 // LHS source location lost, so should never be referenced. Just sort it to the end.
26722675 return false;
......@@ -2684,8 +2687,14 @@ pub const LazySrcLoc = struct {
26842687 return std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).compare(.lt);
26852688 }
26862689
2687 const lhs_span = try lhs_src.span(zcu);
2688 const rhs_span = try rhs_src.span(zcu);
2690 const lhs_span = lhs_src.span(zcu) catch |err| {
2691 bad_file_out.* = lhs_src.file_scope;
2692 return err;
2693 };
2694 const rhs_span = rhs_src.span(zcu) catch |err| {
2695 bad_file_out.* = rhs_src.file_scope;
2696 return err;
2697 };
26892698 return lhs_span.main < rhs_span.main;
26902699 }
26912700};
......@@ -4584,7 +4593,7 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
45844593pub fn addFileInMultipleModulesError(
45854594 zcu: *Zcu,
45864595 eb: *std.zig.ErrorBundle.Wip,
4587) !void {
4596) Allocator.Error!void {
45884597 const gpa = zcu.gpa;
45894598
45904599 const info = zcu.multi_module_err.?;
......@@ -4631,7 +4640,7 @@ fn explainWhyFileIsInModule(
46314640 file: File.Index,
46324641 in_module: *Package.Module,
46334642 ref: File.Reference,
4634) !void {
4643) Allocator.Error!void {
46354644 const gpa = zcu.gpa;
46364645
46374646 // error: file is the root of module 'foo'
......@@ -4666,7 +4675,13 @@ fn explainWhyFileIsInModule(
46664675 const thing: []const u8 = if (is_first) "file" else "which";
46674676 is_first = false;
46684677
4669 const import_src = try zcu.fileByIndex(import.importer).errorBundleTokenSrc(import.tok, zcu, eb);
4678 const importer_file = zcu.fileByIndex(import.importer);
4679 // `errorBundleTokenSrc` expects the tree to be loaded
4680 _ = importer_file.getTree(zcu) catch |err| {
4681 try Compilation.unableToLoadZcuFile(zcu, eb, importer_file, err);
4682 return; // stop the explanation early
4683 };
4684 const import_src = try importer_file.errorBundleTokenSrc(import.tok, zcu, eb);
46704685
46714686 const importer_ref = zcu.alive_files.get(import.importer).?;
46724687 const importer_root: ?*Package.Module = switch (importer_ref) {
src/libs/freebsd.zig+14-5
......@@ -57,7 +57,7 @@ fn libcPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const
5757}
5858
5959/// TODO replace anyerror with explicit error set, recording user-friendly errors with
60/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
60/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
6161pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) anyerror!void {
6262 if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions;
6363
......@@ -414,7 +414,7 @@ fn wordDirective(target: *const std.Target) []const u8 {
414414}
415415
416416/// TODO replace anyerror with explicit error set, recording user-friendly errors with
417/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
417/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
418418pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anyerror!void {
419419 // See also glibc.zig which this code is based on.
420420
......@@ -1065,7 +1065,10 @@ fn buildSharedLib(
10651065 },
10661066 };
10671067
1068 const sub_compilation = try Compilation.create(comp.gpa, arena, .{
1068 const misc_task: Compilation.MiscTask = .@"freebsd libc shared object";
1069
1070 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
1071 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
10691072 .dirs = comp.dirs.withoutLocalCache(),
10701073 .thread_pool = comp.thread_pool,
10711074 .self_exe_path = comp.self_exe_path,
......@@ -1090,8 +1093,14 @@ fn buildSharedLib(
10901093 .soname = soname,
10911094 .c_source_files = &c_source_files,
10921095 .skip_linker_dependencies = true,
1093 });
1096 }) catch |err| switch (err) {
1097 error.CreateFail => {
1098 comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag });
1099 return error.AlreadyReported;
1100 },
1101 else => |e| return e,
1102 };
10941103 defer sub_compilation.destroy();
10951104
1096 try comp.updateSubCompilation(sub_compilation, .@"freebsd libc shared object", prog_node);
1105 try comp.updateSubCompilation(sub_compilation, misc_task, prog_node);
10971106}
src/libs/glibc.zig+14-5
......@@ -162,7 +162,7 @@ pub const CrtFile = enum {
162162};
163163
164164/// TODO replace anyerror with explicit error set, recording user-friendly errors with
165/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
165/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
166166pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) anyerror!void {
167167 if (!build_options.have_llvm) {
168168 return error.ZigCompilerNotBuiltWithLLVMExtensions;
......@@ -656,7 +656,7 @@ fn wordDirective(target: *const std.Target) []const u8 {
656656}
657657
658658/// TODO replace anyerror with explicit error set, recording user-friendly errors with
659/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
659/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
660660pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anyerror!void {
661661 const tracy = trace(@src());
662662 defer tracy.end();
......@@ -1223,7 +1223,10 @@ fn buildSharedLib(
12231223 },
12241224 };
12251225
1226 const sub_compilation = try Compilation.create(comp.gpa, arena, .{
1226 const misc_task: Compilation.MiscTask = .@"glibc shared object";
1227
1228 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
1229 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
12271230 .dirs = comp.dirs.withoutLocalCache(),
12281231 .thread_pool = comp.thread_pool,
12291232 .self_exe_path = comp.self_exe_path,
......@@ -1248,10 +1251,16 @@ fn buildSharedLib(
12481251 .soname = soname,
12491252 .c_source_files = &c_source_files,
12501253 .skip_linker_dependencies = true,
1251 });
1254 }) catch |err| switch (err) {
1255 error.CreateFail => {
1256 comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag });
1257 return error.AlreadyReported;
1258 },
1259 else => |e| return e,
1260 };
12521261 defer sub_compilation.destroy();
12531262
1254 try comp.updateSubCompilation(sub_compilation, .@"glibc shared object", prog_node);
1263 try comp.updateSubCompilation(sub_compilation, misc_task, prog_node);
12551264}
12561265
12571266pub fn needsCrt0(output_mode: std.builtin.OutputMode) ?CrtFile {
src/libs/libcxx.zig+35-35
......@@ -102,7 +102,7 @@ const libcxx_thread_files = [_][]const u8{
102102
103103pub const BuildError = error{
104104 OutOfMemory,
105 SubCompilationFailed,
105 AlreadyReported,
106106 ZigCompilerNotBuiltWithLLVMExtensions,
107107};
108108
......@@ -144,12 +144,12 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
144144 .lto = comp.config.lto,
145145 .any_sanitize_thread = comp.config.any_sanitize_thread,
146146 }) catch |err| {
147 comp.setMiscFailure(
147 comp.lockAndSetMiscFailure(
148148 .libcxx,
149149 "unable to build libc++: resolving configuration failed: {s}",
150150 .{@errorName(err)},
151151 );
152 return error.SubCompilationFailed;
152 return error.AlreadyReported;
153153 };
154154
155155 const root_mod = Module.create(arena, .{
......@@ -177,12 +177,12 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
177177 .cc_argv = &.{},
178178 .parent = null,
179179 }) catch |err| {
180 comp.setMiscFailure(
180 comp.lockAndSetMiscFailure(
181181 .libcxx,
182182 "unable to build libc++: creating module failed: {s}",
183183 .{@errorName(err)},
184184 );
185 return error.SubCompilationFailed;
185 return error.AlreadyReported;
186186 };
187187
188188 const libcxx_files = if (comp.config.any_non_single_threaded)
......@@ -255,7 +255,10 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
255255 });
256256 }
257257
258 const sub_compilation = Compilation.create(comp.gpa, arena, .{
258 const misc_task: Compilation.MiscTask = .libcxx;
259
260 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
261 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
259262 .dirs = comp.dirs.withoutLocalCache(),
260263 .self_exe_path = comp.self_exe_path,
261264 .cache_mode = .whole,
......@@ -276,24 +279,19 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
276279 .clang_passthrough_mode = comp.clang_passthrough_mode,
277280 .skip_linker_dependencies = true,
278281 }) catch |err| {
279 comp.setMiscFailure(
280 .libcxx,
281 "unable to build libc++: create compilation failed: {s}",
282 .{@errorName(err)},
283 );
284 return error.SubCompilationFailed;
282 switch (err) {
283 else => comp.lockAndSetMiscFailure(misc_task, "unable to build libc++: create compilation failed: {t}", .{err}),
284 error.CreateFail => comp.lockAndSetMiscFailure(misc_task, "unable to build libc++: create compilation failed: {f}", .{sub_create_diag}),
285 }
286 return error.AlreadyReported;
285287 };
286288 defer sub_compilation.destroy();
287289
288 comp.updateSubCompilation(sub_compilation, .libcxx, prog_node) catch |err| switch (err) {
289 error.SubCompilationFailed => return error.SubCompilationFailed,
290 comp.updateSubCompilation(sub_compilation, misc_task, prog_node) catch |err| switch (err) {
291 error.AlreadyReported => return error.AlreadyReported,
290292 else => |e| {
291 comp.setMiscFailure(
292 .libcxx,
293 "unable to build libc++: compilation failed: {s}",
294 .{@errorName(e)},
295 );
296 return error.SubCompilationFailed;
293 comp.lockAndSetMiscFailure(misc_task, "unable to build libc++: compilation failed: {t}", .{e});
294 return error.AlreadyReported;
297295 },
298296 };
299297
......@@ -345,12 +343,12 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
345343 .lto = comp.config.lto,
346344 .any_sanitize_thread = comp.config.any_sanitize_thread,
347345 }) catch |err| {
348 comp.setMiscFailure(
346 comp.lockAndSetMiscFailure(
349347 .libcxxabi,
350348 "unable to build libc++abi: resolving configuration failed: {s}",
351349 .{@errorName(err)},
352350 );
353 return error.SubCompilationFailed;
351 return error.AlreadyReported;
354352 };
355353
356354 const root_mod = Module.create(arena, .{
......@@ -379,12 +377,12 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
379377 .cc_argv = &.{},
380378 .parent = null,
381379 }) catch |err| {
382 comp.setMiscFailure(
380 comp.lockAndSetMiscFailure(
383381 .libcxxabi,
384382 "unable to build libc++abi: creating module failed: {s}",
385383 .{@errorName(err)},
386384 );
387 return error.SubCompilationFailed;
385 return error.AlreadyReported;
388386 };
389387
390388 var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxxabi_files.len);
......@@ -446,7 +444,10 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
446444 });
447445 }
448446
449 const sub_compilation = Compilation.create(comp.gpa, arena, .{
447 const misc_task: Compilation.MiscTask = .libcxxabi;
448
449 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
450 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
450451 .dirs = comp.dirs.withoutLocalCache(),
451452 .self_exe_path = comp.self_exe_path,
452453 .cache_mode = .whole,
......@@ -467,24 +468,23 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
467468 .clang_passthrough_mode = comp.clang_passthrough_mode,
468469 .skip_linker_dependencies = true,
469470 }) catch |err| {
470 comp.setMiscFailure(
471 .libcxxabi,
472 "unable to build libc++abi: create compilation failed: {s}",
473 .{@errorName(err)},
474 );
475 return error.SubCompilationFailed;
471 switch (err) {
472 else => comp.lockAndSetMiscFailure(misc_task, "unable to build libc++abi: create compilation failed: {t}", .{err}),
473 error.CreateFail => comp.lockAndSetMiscFailure(misc_task, "unable to build libc++abi: create compilation failed: {f}", .{sub_create_diag}),
474 }
475 return error.AlreadyReported;
476476 };
477477 defer sub_compilation.destroy();
478478
479 comp.updateSubCompilation(sub_compilation, .libcxxabi, prog_node) catch |err| switch (err) {
480 error.SubCompilationFailed => return error.SubCompilationFailed,
479 comp.updateSubCompilation(sub_compilation, misc_task, prog_node) catch |err| switch (err) {
480 error.AlreadyReported => return error.AlreadyReported,
481481 else => |e| {
482 comp.setMiscFailure(
482 comp.lockAndSetMiscFailure(
483483 .libcxxabi,
484484 "unable to build libc++abi: compilation failed: {s}",
485485 .{@errorName(e)},
486486 );
487 return error.SubCompilationFailed;
487 return error.AlreadyReported;
488488 },
489489 };
490490
src/libs/libtsan.zig+19-20
......@@ -8,7 +8,7 @@ const Module = @import("../Package/Module.zig");
88
99pub const BuildError = error{
1010 OutOfMemory,
11 SubCompilationFailed,
11 AlreadyReported,
1212 ZigCompilerNotBuiltWithLLVMExtensions,
1313 TSANUnsupportedCPUArchitecture,
1414};
......@@ -66,12 +66,12 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
6666 // LLVM disables LTO for its libtsan.
6767 .lto = .none,
6868 }) catch |err| {
69 comp.setMiscFailure(
69 comp.lockAndSetMiscFailure(
7070 .libtsan,
7171 "unable to build thread sanitizer runtime: resolving configuration failed: {s}",
7272 .{@errorName(err)},
7373 );
74 return error.SubCompilationFailed;
74 return error.AlreadyReported;
7575 };
7676
7777 const common_flags = [_][]const u8{
......@@ -105,12 +105,12 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
105105 .cc_argv = &common_flags,
106106 .parent = null,
107107 }) catch |err| {
108 comp.setMiscFailure(
108 comp.lockAndSetMiscFailure(
109109 .libtsan,
110110 "unable to build thread sanitizer runtime: creating module failed: {s}",
111111 .{@errorName(err)},
112112 );
113 return error.SubCompilationFailed;
113 return error.AlreadyReported;
114114 };
115115
116116 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
......@@ -273,7 +273,11 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
273273 null;
274274 // Workaround for https://github.com/llvm/llvm-project/issues/97627
275275 const headerpad_size: ?u32 = if (target.os.tag.isDarwin()) 32 else null;
276 const sub_compilation = Compilation.create(comp.gpa, arena, .{
276
277 const misc_task: Compilation.MiscTask = .libtsan;
278
279 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
280 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
277281 .dirs = comp.dirs.withoutLocalCache(),
278282 .thread_pool = comp.thread_pool,
279283 .self_exe_path = comp.self_exe_path,
......@@ -297,24 +301,19 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
297301 .install_name = install_name,
298302 .headerpad_size = headerpad_size,
299303 }) catch |err| {
300 comp.setMiscFailure(
301 .libtsan,
302 "unable to build thread sanitizer runtime: create compilation failed: {s}",
303 .{@errorName(err)},
304 );
305 return error.SubCompilationFailed;
304 switch (err) {
305 else => comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: create compilation failed: {t}", .{ misc_task, err }),
306 error.CreateFail => comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: create compilation failed: {f}", .{ misc_task, sub_create_diag }),
307 }
308 return error.AlreadyReported;
306309 };
307310 defer sub_compilation.destroy();
308311
309 comp.updateSubCompilation(sub_compilation, .libtsan, prog_node) catch |err| switch (err) {
310 error.SubCompilationFailed => return error.SubCompilationFailed,
312 comp.updateSubCompilation(sub_compilation, misc_task, prog_node) catch |err| switch (err) {
313 error.AlreadyReported => return error.AlreadyReported,
311314 else => |e| {
312 comp.setMiscFailure(
313 .libtsan,
314 "unable to build thread sanitizer runtime: compilation failed: {s}",
315 .{@errorName(e)},
316 );
317 return error.SubCompilationFailed;
315 comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: compilation failed: {s}", .{ misc_task, @errorName(e) });
316 return error.AlreadyReported;
318317 },
319318 };
320319
src/libs/libunwind.zig+19-20
......@@ -10,7 +10,7 @@ const trace = @import("../tracy.zig").trace;
1010
1111pub const BuildError = error{
1212 OutOfMemory,
13 SubCompilationFailed,
13 AlreadyReported,
1414 ZigCompilerNotBuiltWithLLVMExtensions,
1515};
1616
......@@ -42,12 +42,12 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
4242 .any_unwind_tables = unwind_tables != .none,
4343 .lto = comp.config.lto,
4444 }) catch |err| {
45 comp.setMiscFailure(
45 comp.lockAndSetMiscFailure(
4646 .libunwind,
4747 "unable to build libunwind: resolving configuration failed: {s}",
4848 .{@errorName(err)},
4949 );
50 return error.SubCompilationFailed;
50 return error.AlreadyReported;
5151 };
5252 const root_mod = Module.create(arena, .{
5353 .paths = .{
......@@ -76,12 +76,12 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
7676 .cc_argv = &.{},
7777 .parent = null,
7878 }) catch |err| {
79 comp.setMiscFailure(
79 comp.lockAndSetMiscFailure(
8080 .libunwind,
8181 "unable to build libunwind: creating module failed: {s}",
8282 .{@errorName(err)},
8383 );
84 return error.SubCompilationFailed;
84 return error.AlreadyReported;
8585 };
8686
8787 const root_name = "unwind";
......@@ -139,7 +139,11 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
139139 .owner = root_mod,
140140 };
141141 }
142 const sub_compilation = Compilation.create(comp.gpa, arena, .{
142
143 const misc_task: Compilation.MiscTask = .libunwind;
144
145 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
146 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
143147 .dirs = comp.dirs.withoutLocalCache(),
144148 .self_exe_path = comp.self_exe_path,
145149 .config = config,
......@@ -162,24 +166,19 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
162166 .clang_passthrough_mode = comp.clang_passthrough_mode,
163167 .skip_linker_dependencies = true,
164168 }) catch |err| {
165 comp.setMiscFailure(
166 .libunwind,
167 "unable to build libunwind: create compilation failed: {s}",
168 .{@errorName(err)},
169 );
170 return error.SubCompilationFailed;
169 switch (err) {
170 else => comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: create compilation failed: {t}", .{ misc_task, err }),
171 error.CreateFail => comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: create compilation failed: {f}", .{ misc_task, sub_create_diag }),
172 }
173 return error.AlreadyReported;
171174 };
172175 defer sub_compilation.destroy();
173176
174 comp.updateSubCompilation(sub_compilation, .libunwind, prog_node) catch |err| switch (err) {
175 error.SubCompilationFailed => return error.SubCompilationFailed,
177 comp.updateSubCompilation(sub_compilation, misc_task, prog_node) catch |err| switch (err) {
178 error.AlreadyReported => return error.AlreadyReported,
176179 else => |e| {
177 comp.setMiscFailure(
178 .libunwind,
179 "unable to build libunwind: compilation failed: {s}",
180 .{@errorName(e)},
181 );
182 return error.SubCompilationFailed;
180 comp.lockAndSetMiscFailure(misc_task, "unable to build {t}: compilation failed: {s}", .{ misc_task, @errorName(e) });
181 return error.AlreadyReported;
183182 },
184183 };
185184
src/libs/mingw.zig+1-1
......@@ -18,7 +18,7 @@ pub const CrtFile = enum {
1818};
1919
2020/// TODO replace anyerror with explicit error set, recording user-friendly errors with
21/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
21/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
2222pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) anyerror!void {
2323 if (!build_options.have_llvm) {
2424 return error.ZigCompilerNotBuiltWithLLVMExtensions;
src/libs/musl.zig+13-4
......@@ -17,7 +17,7 @@ pub const CrtFile = enum {
1717};
1818
1919/// TODO replace anyerror with explicit error set, recording user-friendly errors with
20/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
20/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
2121pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Progress.Node) anyerror!void {
2222 if (!build_options.have_llvm) {
2323 return error.ZigCompilerNotBuiltWithLLVMExtensions;
......@@ -243,7 +243,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
243243 .parent = null,
244244 });
245245
246 const sub_compilation = try Compilation.create(comp.gpa, arena, .{
246 const misc_task: Compilation.MiscTask = .@"musl libc.so";
247
248 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
249 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
247250 .dirs = comp.dirs.withoutLocalCache(),
248251 .self_exe_path = comp.self_exe_path,
249252 .cache_mode = .whole,
......@@ -268,10 +271,16 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
268271 },
269272 .skip_linker_dependencies = true,
270273 .soname = "libc.so",
271 });
274 }) catch |err| switch (err) {
275 error.CreateFail => {
276 comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag });
277 return error.AlreadyReported;
278 },
279 else => |e| return e,
280 };
272281 defer sub_compilation.destroy();
273282
274 try comp.updateSubCompilation(sub_compilation, .@"musl libc.so", prog_node);
283 try comp.updateSubCompilation(sub_compilation, misc_task, prog_node);
275284
276285 const basename = try comp.gpa.dupe(u8, "libc.so");
277286 errdefer comp.gpa.free(basename);
src/libs/netbsd.zig+14-5
......@@ -49,7 +49,7 @@ fn csuPath(comp: *Compilation, arena: Allocator, sub_path: []const u8) ![]const
4949}
5050
5151/// TODO replace anyerror with explicit error set, recording user-friendly errors with
52/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
52/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
5353pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) anyerror!void {
5454 if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions;
5555
......@@ -360,7 +360,7 @@ fn wordDirective(target: *const std.Target) []const u8 {
360360}
361361
362362/// TODO replace anyerror with explicit error set, recording user-friendly errors with
363/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
363/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
364364pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anyerror!void {
365365 // See also glibc.zig which this code is based on.
366366
......@@ -729,7 +729,10 @@ fn buildSharedLib(
729729 },
730730 };
731731
732 const sub_compilation = try Compilation.create(comp.gpa, arena, .{
732 const misc_task: Compilation.MiscTask = .@"netbsd libc shared object";
733
734 var sub_create_diag: Compilation.CreateDiagnostic = undefined;
735 const sub_compilation = Compilation.create(comp.gpa, arena, &sub_create_diag, .{
733736 .dirs = comp.dirs.withoutLocalCache(),
734737 .thread_pool = comp.thread_pool,
735738 .self_exe_path = comp.self_exe_path,
......@@ -753,8 +756,14 @@ fn buildSharedLib(
753756 .soname = soname,
754757 .c_source_files = &c_source_files,
755758 .skip_linker_dependencies = true,
756 });
759 }) catch |err| switch (err) {
760 error.CreateFail => {
761 comp.lockAndSetMiscFailure(misc_task, "sub-compilation of {t} failed: {f}", .{ misc_task, sub_create_diag });
762 return error.AlreadyReported;
763 },
764 else => |e| return e,
765 };
757766 defer sub_compilation.destroy();
758767
759 try comp.updateSubCompilation(sub_compilation, .@"netbsd libc shared object", prog_node);
768 try comp.updateSubCompilation(sub_compilation, misc_task, prog_node);
760769}
src/libs/wasi_libc.zig+1-1
......@@ -28,7 +28,7 @@ pub fn execModelCrtFileFullName(wasi_exec_model: std.builtin.WasiExecModel) []co
2828}
2929
3030/// TODO replace anyerror with explicit error set, recording user-friendly errors with
31/// setMiscFailure and returning error.SubCompilationFailed. see libcxx.zig for example.
31/// lockAndSetMiscFailure and returning error.AlreadyReported. see libcxx.zig for example.
3232pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progress.Node) anyerror!void {
3333 if (!build_options.have_llvm) {
3434 return error.ZigCompilerNotBuiltWithLLVMExtensions;
src/link.zig+2
......@@ -509,6 +509,8 @@ pub const File = struct {
509509 };
510510 };
511511
512 pub const OpenError = @typeInfo(@typeInfo(@TypeOf(open)).@"fn".return_type.?).error_union.error_set;
513
512514 /// Attempts incremental linking, if the file already exists. If
513515 /// incremental linking fails, falls back to truncating the file and
514516 /// rewriting it. A malicious file is detected as incremental link failure
src/main.zig+58-50
......@@ -3395,7 +3395,8 @@ fn buildOutputType(
33953395 var file_system_inputs: std.ArrayListUnmanaged(u8) = .empty;
33963396 defer file_system_inputs.deinit(gpa);
33973397
3398 const comp = Compilation.create(gpa, arena, .{
3398 var create_diag: Compilation.CreateDiagnostic = undefined;
3399 const comp = Compilation.create(gpa, arena, &create_diag, .{
33993400 .dirs = dirs,
34003401 .thread_pool = &thread_pool,
34013402 .self_exe_path = switch (native_os) {
......@@ -3521,47 +3522,45 @@ fn buildOutputType(
35213522 .file_system_inputs = &file_system_inputs,
35223523 .debug_compiler_runtime_libs = debug_compiler_runtime_libs,
35233524 }) catch |err| switch (err) {
3524 error.LibCUnavailable => {
3525 const triple_name = try target.zigTriple(arena);
3526 std.log.err("unable to find or provide libc for target '{s}'", .{triple_name});
3527
3528 for (std.zig.target.available_libcs) |t| {
3529 if (t.arch == target.cpu.arch and t.os == target.os.tag) {
3530 // If there's a `glibc_min`, there's also an `os_ver`.
3531 if (t.glibc_min) |glibc_min| {
3532 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}.{d}.{d}", .{
3533 @tagName(t.arch),
3534 @tagName(t.os),
3535 t.os_ver.?,
3536 @tagName(t.abi),
3537 glibc_min.major,
3538 glibc_min.minor,
3539 });
3540 } else if (t.os_ver) |os_ver| {
3541 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}", .{
3542 @tagName(t.arch),
3543 @tagName(t.os),
3544 os_ver,
3545 @tagName(t.abi),
3546 });
3547 } else {
3548 std.log.info("zig can provide libc for related target {s}-{s}-{s}", .{
3549 @tagName(t.arch),
3550 @tagName(t.os),
3551 @tagName(t.abi),
3552 });
3525 error.CreateFail => switch (create_diag) {
3526 .cross_libc_unavailable => {
3527 // We can emit a more informative error for this.
3528 const triple_name = try target.zigTriple(arena);
3529 std.log.err("unable to provide libc for target '{s}'", .{triple_name});
3530
3531 for (std.zig.target.available_libcs) |t| {
3532 if (t.arch == target.cpu.arch and t.os == target.os.tag) {
3533 // If there's a `glibc_min`, there's also an `os_ver`.
3534 if (t.glibc_min) |glibc_min| {
3535 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}.{d}.{d}", .{
3536 @tagName(t.arch),
3537 @tagName(t.os),
3538 t.os_ver.?,
3539 @tagName(t.abi),
3540 glibc_min.major,
3541 glibc_min.minor,
3542 });
3543 } else if (t.os_ver) |os_ver| {
3544 std.log.info("zig can provide libc for related target {s}-{s}.{f}-{s}", .{
3545 @tagName(t.arch),
3546 @tagName(t.os),
3547 os_ver,
3548 @tagName(t.abi),
3549 });
3550 } else {
3551 std.log.info("zig can provide libc for related target {s}-{s}-{s}", .{
3552 @tagName(t.arch),
3553 @tagName(t.os),
3554 @tagName(t.abi),
3555 });
3556 }
35533557 }
35543558 }
3555 }
3556 process.exit(1);
3557 },
3558 error.ExportTableAndImportTableConflict => {
3559 fatal("--import-table and --export-table may not be used together", .{});
3560 },
3561 error.IllegalZigImport => {
3562 fatal("this compiler implementation does not support importing the root source file of a provided module", .{});
3559 process.exit(1);
3560 },
3561 else => fatal("{f}", .{create_diag}),
35633562 },
3564 else => fatal("unable to create compilation: {s}", .{@errorName(err)}),
3563 else => fatal("failed to create compilation: {s}", .{@errorName(err)}),
35653564 };
35663565 var comp_destroyed = false;
35673566 defer if (!comp_destroyed) comp.destroy();
......@@ -3627,7 +3626,7 @@ fn buildOutputType(
36273626 }
36283627
36293628 updateModule(comp, color, root_prog_node) catch |err| switch (err) {
3630 error.SemanticAnalyzeFail => {
3629 error.CompileErrorsReported => {
36313630 assert(listen == .none);
36323631 saveState(comp, incremental);
36333632 process.exit(1);
......@@ -4521,7 +4520,12 @@ fn runOrTestHotSwap(
45214520 }
45224521}
45234522
4524fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node) !void {
4523const UpdateModuleError = Compilation.UpdateError || error{
4524 /// The update caused compile errors. The error bundle has already been
4525 /// reported to the user by being rendered to stderr.
4526 CompileErrorsReported,
4527};
4528fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node) UpdateModuleError!void {
45254529 try comp.update(prog_node);
45264530
45274531 var errors = try comp.getAllErrorsAlloc();
......@@ -4529,7 +4533,7 @@ fn updateModule(comp: *Compilation, color: Color, prog_node: std.Progress.Node)
45294533
45304534 if (errors.errorMessageCount() > 0) {
45314535 errors.renderToStdErr(color.renderOptions());
4532 return error.SemanticAnalyzeFail;
4536 return error.CompileErrorsReported;
45334537 }
45344538}
45354539
......@@ -5373,7 +5377,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
53735377
53745378 try root_mod.deps.put(arena, "@build", build_mod);
53755379
5376 const comp = Compilation.create(gpa, arena, .{
5380 var create_diag: Compilation.CreateDiagnostic = undefined;
5381 const comp = Compilation.create(gpa, arena, &create_diag, .{
53775382 .libc_installation = libc_installation,
53785383 .dirs = dirs,
53795384 .root_name = "build",
......@@ -5395,13 +5400,14 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
53955400 .cache_mode = .whole,
53965401 .reference_trace = reference_trace,
53975402 .debug_compile_errors = debug_compile_errors,
5398 }) catch |err| {
5399 fatal("unable to create compilation: {s}", .{@errorName(err)});
5403 }) catch |err| switch (err) {
5404 error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}),
5405 else => fatal("failed to create compilation: {s}", .{@errorName(err)}),
54005406 };
54015407 defer comp.destroy();
54025408
54035409 updateModule(comp, color, root_prog_node) catch |err| switch (err) {
5404 error.SemanticAnalyzeFail => process.exit(2),
5410 error.CompileErrorsReported => process.exit(2),
54055411 else => |e| return e,
54065412 };
54075413
......@@ -5614,7 +5620,8 @@ fn jitCmd(
56145620 try root_mod.deps.put(arena, "aro", aro_mod);
56155621 }
56165622
5617 const comp = Compilation.create(gpa, arena, .{
5623 var create_diag: Compilation.CreateDiagnostic = undefined;
5624 const comp = Compilation.create(gpa, arena, &create_diag, .{
56185625 .dirs = dirs,
56195626 .root_name = options.cmd_name,
56205627 .config = config,
......@@ -5624,8 +5631,9 @@ fn jitCmd(
56245631 .self_exe_path = self_exe_path,
56255632 .thread_pool = &thread_pool,
56265633 .cache_mode = .whole,
5627 }) catch |err| {
5628 fatal("unable to create compilation: {s}", .{@errorName(err)});
5634 }) catch |err| switch (err) {
5635 error.CreateFail => fatal("failed to create compilation: {f}", .{create_diag}),
5636 else => fatal("failed to create compilation: {s}", .{@errorName(err)}),
56295637 };
56305638 defer comp.destroy();
56315639
......@@ -5646,7 +5654,7 @@ fn jitCmd(
56465654 }
56475655 } else {
56485656 updateModule(comp, color, root_prog_node) catch |err| switch (err) {
5649 error.SemanticAnalyzeFail => process.exit(2),
5657 error.CompileErrorsReported => process.exit(2),
56505658 else => |e| return e,
56515659 };
56525660 }