Commit 90e48d4b34

Andrew Kelley <andrew@ziglang.org>
2023-01-31 22:02:32
std.Build: avoid use of catch unreachable
Usage of `catch unreachable` in build scripts is completely harmless because build scripts are always run in Debug mode, however, it sets a poor example for beginners to learn from.
1 parent 13a9616
lib/std/Build/CheckFileStep.zig
@@ -18,7 +18,7 @@ pub fn create(
     source: std.Build.FileSource,
     expected_matches: []const []const u8,
 ) *CheckFileStep {
-    const self = builder.allocator.create(CheckFileStep) catch unreachable;
+    const self = builder.allocator.create(CheckFileStep) catch @panic("OOM");
     self.* = CheckFileStep{
         .builder = builder,
         .step = Step.init(.check_file, "CheckFile", builder.allocator, make),
lib/std/Build/CheckObjectStep.zig
@@ -24,7 +24,7 @@ obj_format: std.Target.ObjectFormat,
 
 pub fn create(builder: *std.Build, source: std.Build.FileSource, obj_format: std.Target.ObjectFormat) *CheckObjectStep {
     const gpa = builder.allocator;
-    const self = gpa.create(CheckObjectStep) catch unreachable;
+    const self = gpa.create(CheckObjectStep) catch @panic("OOM");
     self.* = .{
         .builder = builder,
         .step = Step.init(.check_file, "CheckObject", gpa, make),
@@ -228,14 +228,14 @@ const Check = struct {
         self.actions.append(.{
             .tag = .match,
             .phrase = self.builder.dupe(phrase),
-        }) catch unreachable;
+        }) catch @panic("OOM");
     }
 
     fn notPresent(self: *Check, phrase: []const u8) void {
         self.actions.append(.{
             .tag = .not_present,
             .phrase = self.builder.dupe(phrase),
-        }) catch unreachable;
+        }) catch @panic("OOM");
     }
 
     fn computeCmp(self: *Check, phrase: []const u8, expected: ComputeCompareExpected) void {
@@ -243,7 +243,7 @@ const Check = struct {
             .tag = .compute_cmp,
             .phrase = self.builder.dupe(phrase),
             .expected = expected,
-        }) catch unreachable;
+        }) catch @panic("OOM");
     }
 };
 
@@ -251,7 +251,7 @@ const Check = struct {
 pub fn checkStart(self: *CheckObjectStep, phrase: []const u8) void {
     var new_check = Check.create(self.builder);
     new_check.match(phrase);
-    self.checks.append(new_check) catch unreachable;
+    self.checks.append(new_check) catch @panic("OOM");
 }
 
 /// Adds another searched phrase to the latest created Check with `CheckObjectStep.checkStart(...)`.
@@ -293,7 +293,7 @@ pub fn checkComputeCompare(
 ) void {
     var new_check = Check.create(self.builder);
     new_check.computeCmp(program, expected);
-    self.checks.append(new_check) catch unreachable;
+    self.checks.append(new_check) catch @panic("OOM");
 }
 
 fn make(step: *Step) !void {
lib/std/Build/CompileStep.zig
@@ -312,7 +312,7 @@ pub fn create(builder: *std.Build, options: Options) *CompileStep {
         panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
     }
 
-    const self = builder.allocator.create(CompileStep) catch unreachable;
+    const self = builder.allocator.create(CompileStep) catch @panic("OOM");
     self.* = CompileStep{
         .strip = null,
         .unwind_tables = null,
@@ -364,7 +364,7 @@ pub fn create(builder: *std.Build, options: Options) *CompileStep {
         .output_h_path_source = GeneratedFile{ .step = &self.step },
         .output_pdb_path_source = GeneratedFile{ .step = &self.step },
 
-        .target_info = NativeTargetInfo.detect(self.target) catch unreachable,
+        .target_info = NativeTargetInfo.detect(self.target) catch @panic("unhandled error"),
     };
     self.computeOutFileNames();
     if (root_src) |rs| rs.addStepDependencies(&self.step);
@@ -387,7 +387,7 @@ fn computeOutFileNames(self: *CompileStep) void {
             .static => .Static,
         }) else null,
         .version = self.version,
-    }) catch unreachable;
+    }) catch @panic("OOM");
 
     if (self.kind == .lib) {
         if (self.linkage != null and self.linkage.? == .static) {
@@ -439,7 +439,7 @@ pub fn installRaw(self: *CompileStep, dest_filename: []const u8, options: Instal
 pub fn installHeader(a: *CompileStep, src_path: []const u8, dest_rel_path: []const u8) void {
     const install_file = a.builder.addInstallHeaderFile(src_path, dest_rel_path);
     a.builder.getInstallStep().dependOn(&install_file.step);
-    a.installed_headers.append(&install_file.step) catch unreachable;
+    a.installed_headers.append(&install_file.step) catch @panic("OOM");
 }
 
 pub fn installHeadersDirectory(
@@ -460,7 +460,7 @@ pub fn installHeadersDirectoryOptions(
 ) void {
     const install_dir = a.builder.addInstallDirectory(options);
     a.builder.getInstallStep().dependOn(&install_dir.step);
-    a.installed_headers.append(&install_dir.step) catch unreachable;
+    a.installed_headers.append(&install_dir.step) catch @panic("OOM");
 }
 
 pub fn installLibraryHeaders(a: *CompileStep, l: *CompileStep) void {
@@ -472,7 +472,7 @@ pub fn installLibraryHeaders(a: *CompileStep, l: *CompileStep) void {
         const step_copy = switch (step.id) {
             inline .install_file, .install_dir => |id| blk: {
                 const T = id.Type();
-                const ptr = a.builder.allocator.create(T) catch unreachable;
+                const ptr = a.builder.allocator.create(T) catch @panic("OOM");
                 ptr.* = step.cast(T).?.*;
                 ptr.override_source_builder = ptr.builder;
                 ptr.builder = a.builder;
@@ -480,10 +480,10 @@ pub fn installLibraryHeaders(a: *CompileStep, l: *CompileStep) void {
             },
             else => unreachable,
         };
-        a.installed_headers.append(step_copy) catch unreachable;
+        a.installed_headers.append(step_copy) catch @panic("OOM");
         install_step.dependOn(step_copy);
     }
-    a.installed_headers.appendSlice(l.installed_headers.items) catch unreachable;
+    a.installed_headers.appendSlice(l.installed_headers.items) catch @panic("OOM");
 }
 
 /// Creates a `RunStep` with an executable built with `addExecutable`.
@@ -532,19 +532,19 @@ pub fn setLinkerScriptPath(self: *CompileStep, source: FileSource) void {
 }
 
 pub fn linkFramework(self: *CompileStep, framework_name: []const u8) void {
-    self.frameworks.put(self.builder.dupe(framework_name), .{}) catch unreachable;
+    self.frameworks.put(self.builder.dupe(framework_name), .{}) catch @panic("OOM");
 }
 
 pub fn linkFrameworkNeeded(self: *CompileStep, framework_name: []const u8) void {
     self.frameworks.put(self.builder.dupe(framework_name), .{
         .needed = true,
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 pub fn linkFrameworkWeak(self: *CompileStep, framework_name: []const u8) void {
     self.frameworks.put(self.builder.dupe(framework_name), .{
         .weak = true,
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 /// Returns whether the library, executable, or object depends on a particular system library.
@@ -596,12 +596,12 @@ pub fn linkLibCpp(self: *CompileStep) void {
 /// `name` and `value` need not live longer than the function call.
 pub fn defineCMacro(self: *CompileStep, name: []const u8, value: ?[]const u8) void {
     const macro = std.Build.constructCMacro(self.builder.allocator, name, value);
-    self.c_macros.append(macro) catch unreachable;
+    self.c_macros.append(macro) catch @panic("OOM");
 }
 
 /// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1.
 pub fn defineCMacroRaw(self: *CompileStep, name_and_value: []const u8) void {
-    self.c_macros.append(self.builder.dupe(name_and_value)) catch unreachable;
+    self.c_macros.append(self.builder.dupe(name_and_value)) catch @panic("OOM");
 }
 
 /// This one has no integration with anything, it just puts -lname on the command line.
@@ -614,7 +614,7 @@ pub fn linkSystemLibraryName(self: *CompileStep, name: []const u8) void {
             .weak = false,
             .use_pkg_config = .no,
         },
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 /// This one has no integration with anything, it just puts -needed-lname on the command line.
@@ -627,7 +627,7 @@ pub fn linkSystemLibraryNeededName(self: *CompileStep, name: []const u8) void {
             .weak = false,
             .use_pkg_config = .no,
         },
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 /// Darwin-only. This one has no integration with anything, it just puts -weak-lname on the
@@ -640,7 +640,7 @@ pub fn linkSystemLibraryWeakName(self: *CompileStep, name: []const u8) void {
             .weak = true,
             .use_pkg_config = .no,
         },
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 /// This links against a system library, exclusively using pkg-config to find the library.
@@ -653,7 +653,7 @@ pub fn linkSystemLibraryPkgConfigOnly(self: *CompileStep, lib_name: []const u8)
             .weak = false,
             .use_pkg_config = .force,
         },
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 /// This links against a system library, exclusively using pkg-config to find the library.
@@ -666,7 +666,7 @@ pub fn linkSystemLibraryNeededPkgConfigOnly(self: *CompileStep, lib_name: []cons
             .weak = false,
             .use_pkg_config = .force,
         },
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 /// Run pkg-config for the given library name and parse the output, returning the arguments
@@ -797,7 +797,7 @@ fn linkSystemLibraryInner(self: *CompileStep, name: []const u8, opts: struct {
             .weak = opts.weak,
             .use_pkg_config = .yes,
         },
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 pub fn setNamePrefix(self: *CompileStep, text: []const u8) void {
@@ -817,7 +817,7 @@ pub fn setTestRunner(self: *CompileStep, path: ?[]const u8) void {
 
 /// Handy when you have many C/C++ source files and want them all to have the same flags.
 pub fn addCSourceFiles(self: *CompileStep, files: []const []const u8, flags: []const []const u8) void {
-    const c_source_files = self.builder.allocator.create(CSourceFiles) catch unreachable;
+    const c_source_files = self.builder.allocator.create(CSourceFiles) catch @panic("OOM");
 
     const files_copy = self.builder.dupeStrings(files);
     const flags_copy = self.builder.dupeStrings(flags);
@@ -826,7 +826,7 @@ pub fn addCSourceFiles(self: *CompileStep, files: []const []const u8, flags: []c
         .files = files_copy,
         .flags = flags_copy,
     };
-    self.link_objects.append(.{ .c_source_files = c_source_files }) catch unreachable;
+    self.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM");
 }
 
 pub fn addCSourceFile(self: *CompileStep, file: []const u8, flags: []const []const u8) void {
@@ -837,9 +837,9 @@ pub fn addCSourceFile(self: *CompileStep, file: []const u8, flags: []const []con
 }
 
 pub fn addCSourceFileSource(self: *CompileStep, source: CSourceFile) void {
-    const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable;
+    const c_source_file = self.builder.allocator.create(CSourceFile) catch @panic("OOM");
     c_source_file.* = source.dupe(self.builder);
-    self.link_objects.append(.{ .c_source_file = c_source_file }) catch unreachable;
+    self.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM");
     source.source.addStepDependencies(&self.step);
 }
 
@@ -893,12 +893,12 @@ pub fn getOutputPdbSource(self: *CompileStep) FileSource {
 pub fn addAssemblyFile(self: *CompileStep, path: []const u8) void {
     self.link_objects.append(.{
         .assembly_file = .{ .path = self.builder.dupe(path) },
-    }) catch unreachable;
+    }) catch @panic("OOM");
 }
 
 pub fn addAssemblyFileSource(self: *CompileStep, source: FileSource) void {
     const source_duped = source.dupe(self.builder);
-    self.link_objects.append(.{ .assembly_file = source_duped }) catch unreachable;
+    self.link_objects.append(.{ .assembly_file = source_duped }) catch @panic("OOM");
     source_duped.addStepDependencies(&self.step);
 }
 
@@ -907,7 +907,7 @@ pub fn addObjectFile(self: *CompileStep, source_file: []const u8) void {
 }
 
 pub fn addObjectFileSource(self: *CompileStep, source: FileSource) void {
-    self.link_objects.append(.{ .static_path = source.dupe(self.builder) }) catch unreachable;
+    self.link_objects.append(.{ .static_path = source.dupe(self.builder) }) catch @panic("OOM");
     source.addStepDependencies(&self.step);
 }
 
@@ -922,11 +922,11 @@ pub const addLibPath = @compileError("deprecated, use addLibraryPath");
 pub const addFrameworkDir = @compileError("deprecated, use addFrameworkPath");
 
 pub fn addSystemIncludePath(self: *CompileStep, path: []const u8) void {
-    self.include_dirs.append(IncludeDir{ .raw_path_system = self.builder.dupe(path) }) catch unreachable;
+    self.include_dirs.append(IncludeDir{ .raw_path_system = self.builder.dupe(path) }) catch @panic("OOM");
 }
 
 pub fn addIncludePath(self: *CompileStep, path: []const u8) void {
-    self.include_dirs.append(IncludeDir{ .raw_path = self.builder.dupe(path) }) catch unreachable;
+    self.include_dirs.append(IncludeDir{ .raw_path = self.builder.dupe(path) }) catch @panic("OOM");
 }
 
 pub fn addConfigHeader(self: *CompileStep, config_header: *ConfigHeaderStep) void {
@@ -935,19 +935,19 @@ pub fn addConfigHeader(self: *CompileStep, config_header: *ConfigHeaderStep) voi
 }
 
 pub fn addLibraryPath(self: *CompileStep, path: []const u8) void {
-    self.lib_paths.append(self.builder.dupe(path)) catch unreachable;
+    self.lib_paths.append(self.builder.dupe(path)) catch @panic("OOM");
 }
 
 pub fn addRPath(self: *CompileStep, path: []const u8) void {
-    self.rpaths.append(self.builder.dupe(path)) catch unreachable;
+    self.rpaths.append(self.builder.dupe(path)) catch @panic("OOM");
 }
 
 pub fn addFrameworkPath(self: *CompileStep, dir_path: []const u8) void {
-    self.framework_dirs.append(self.builder.dupe(dir_path)) catch unreachable;
+    self.framework_dirs.append(self.builder.dupe(dir_path)) catch @panic("OOM");
 }
 
 pub fn addPackage(self: *CompileStep, package: Pkg) void {
-    self.packages.append(self.builder.dupePkg(package)) catch unreachable;
+    self.packages.append(self.builder.dupePkg(package)) catch @panic("OOM");
     self.addRecursiveBuildDeps(package);
 }
 
@@ -1010,7 +1010,7 @@ pub fn addVcpkgPaths(self: *CompileStep, linkage: CompileStep.Linkage) !void {
 
 pub fn setExecCmd(self: *CompileStep, args: []const ?[]const u8) void {
     assert(self.kind == .@"test");
-    const duped_args = self.builder.allocator.alloc(?[]u8, args.len) catch unreachable;
+    const duped_args = self.builder.allocator.alloc(?[]u8, args.len) catch @panic("OOM");
     for (args) |arg, i| {
         duped_args[i] = if (arg) |a| self.builder.dupe(a) else null;
     }
@@ -1019,8 +1019,8 @@ pub fn setExecCmd(self: *CompileStep, args: []const ?[]const u8) void {
 
 fn linkLibraryOrObject(self: *CompileStep, other: *CompileStep) void {
     self.step.dependOn(&other.step);
-    self.link_objects.append(.{ .other_step = other }) catch unreachable;
-    self.include_dirs.append(.{ .other_step = other }) catch unreachable;
+    self.link_objects.append(.{ .other_step = other }) catch @panic("OOM");
+    self.include_dirs.append(.{ .other_step = other }) catch @panic("OOM");
 }
 
 fn makePackageCmd(self: *CompileStep, pkg: Pkg, zig_args: *ArrayList([]const u8)) error{OutOfMemory}!void {
@@ -1051,7 +1051,7 @@ fn make(step: *Step) !void {
     var zig_args = ArrayList([]const u8).init(builder.allocator);
     defer zig_args.deinit();
 
-    zig_args.append(builder.zig_exe) catch unreachable;
+    try zig_args.append(builder.zig_exe);
 
     const cmd = switch (self.kind) {
         .lib => "build-lib",
@@ -1060,7 +1060,7 @@ fn make(step: *Step) !void {
         .@"test" => "test",
         .test_exe => "test",
     };
-    zig_args.append(cmd) catch unreachable;
+    try zig_args.append(cmd);
 
     if (builder.color != .auto) {
         try zig_args.append("--color");
@@ -1265,12 +1265,12 @@ fn make(step: *Step) !void {
         try zig_args.append("--debug-compile-errors");
     }
 
-    if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable;
-    if (builder.verbose_air) zig_args.append("--verbose-air") catch unreachable;
-    if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable;
-    if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;
-    if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable;
-    if (builder.verbose_llvm_cpu_features) zig_args.append("--verbose-llvm-cpu-features") catch unreachable;
+    if (builder.verbose_cimport) try zig_args.append("--verbose-cimport");
+    if (builder.verbose_air) try zig_args.append("--verbose-air");
+    if (builder.verbose_llvm_ir) try zig_args.append("--verbose-llvm-ir");
+    if (builder.verbose_link or self.verbose_link) try zig_args.append("--verbose-link");
+    if (builder.verbose_cc or self.verbose_cc) try zig_args.append("--verbose-cc");
+    if (builder.verbose_llvm_cpu_features) try zig_args.append("--verbose-llvm-cpu-features");
 
     if (self.emit_analysis.getArg(builder, "emit-analysis")) |arg| try zig_args.append(arg);
     if (self.emit_asm.getArg(builder, "emit-asm")) |arg| try zig_args.append(arg);
@@ -1336,7 +1336,7 @@ fn make(step: *Step) !void {
 
     switch (self.optimize) {
         .Debug => {}, // Skip since it's the default.
-        else => zig_args.append(builder.fmt("-O{s}", .{@tagName(self.optimize)})) catch unreachable,
+        else => try zig_args.append(builder.fmt("-O{s}", .{@tagName(self.optimize)})),
     }
 
     try zig_args.append("--cache-dir");
@@ -1345,8 +1345,8 @@ fn make(step: *Step) !void {
     try zig_args.append("--global-cache-dir");
     try zig_args.append(builder.pathFromRoot(builder.global_cache_root));
 
-    zig_args.append("--name") catch unreachable;
-    zig_args.append(self.name) catch unreachable;
+    try zig_args.append("--name");
+    try zig_args.append(self.name);
 
     if (self.linkage) |some| switch (some) {
         .dynamic => try zig_args.append("-dynamic"),
@@ -1354,8 +1354,8 @@ fn make(step: *Step) !void {
     };
     if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic) {
         if (self.version) |version| {
-            zig_args.append("--version") catch unreachable;
-            zig_args.append(builder.fmt("{}", .{version})) catch unreachable;
+            try zig_args.append("--version");
+            try zig_args.append(builder.fmt("{}", .{version}));
         }
 
         if (self.target.isDarwin()) {
@@ -1651,13 +1651,13 @@ fn make(step: *Step) !void {
             const name = entry.key_ptr.*;
             const info = entry.value_ptr.*;
             if (info.needed) {
-                zig_args.append("-needed_framework") catch unreachable;
+                try zig_args.append("-needed_framework");
             } else if (info.weak) {
-                zig_args.append("-weak_framework") catch unreachable;
+                try zig_args.append("-weak_framework");
             } else {
-                zig_args.append("-framework") catch unreachable;
+                try zig_args.append("-framework");
             }
-            zig_args.append(name) catch unreachable;
+            try zig_args.append(name);
         }
     } else {
         if (self.framework_dirs.items.len > 0) {
@@ -1748,7 +1748,7 @@ fn make(step: *Step) !void {
                     // Slow path for arguments that need to be escaped. We'll need to allocate and copy
                     var escaped = try ArrayList(u8).initCapacity(args_arena.allocator(), arg.len + 1);
                     const writer = escaped.writer();
-                    writer.writeAll(arg[0..arg_idx]) catch unreachable;
+                    try writer.writeAll(arg[0..arg_idx]);
                     for (arg[arg_idx..]) |to_escape| {
                         if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\');
                         try writer.writeByte(to_escape);
@@ -1874,23 +1874,28 @@ fn findVcpkgRoot(allocator: Allocator) !?[]const u8 {
     return vcpkg_path;
 }
 
-pub fn doAtomicSymLinks(allocator: Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void {
+pub fn doAtomicSymLinks(
+    allocator: Allocator,
+    output_path: []const u8,
+    filename_major_only: []const u8,
+    filename_name_only: []const u8,
+) !void {
     const out_dir = fs.path.dirname(output_path) orelse ".";
     const out_basename = fs.path.basename(output_path);
     // sym link for libfoo.so.1 to libfoo.so.1.2.3
-    const major_only_path = fs.path.join(
+    const major_only_path = try fs.path.join(
         allocator,
         &[_][]const u8{ out_dir, filename_major_only },
-    ) catch unreachable;
+    );
     fs.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
         log.err("Unable to symlink {s} -> {s}", .{ major_only_path, out_basename });
         return err;
     };
     // sym link for libfoo.so to libfoo.so.1
-    const name_only_path = fs.path.join(
+    const name_only_path = try fs.path.join(
         allocator,
         &[_][]const u8{ out_dir, filename_name_only },
-    ) catch unreachable;
+    );
     fs.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
         log.err("Unable to symlink {s} -> {s}", .{ name_only_path, filename_major_only });
         return err;
lib/std/Build/EmulatableRunStep.zig
@@ -47,7 +47,7 @@ hide_foreign_binaries_warning: bool,
 /// Asserts given artifact is an executable.
 pub fn create(builder: *std.Build, name: []const u8, artifact: *CompileStep) *EmulatableRunStep {
     std.debug.assert(artifact.kind == .exe or artifact.kind == .test_exe);
-    const self = builder.allocator.create(EmulatableRunStep) catch unreachable;
+    const self = builder.allocator.create(EmulatableRunStep) catch @panic("OOM");
 
     const option_name = "hide-foreign-warnings";
     const hide_warnings = if (builder.available_options_map.get(option_name) == null) warn: {
@@ -154,9 +154,9 @@ fn warnAboutForeignBinaries(step: *EmulatableRunStep) void {
     const builder = step.builder;
     const artifact = step.exe;
 
-    const host_name = builder.host.target.zigTriple(builder.allocator) catch unreachable;
-    const foreign_name = artifact.target.zigTriple(builder.allocator) catch unreachable;
-    const target_info = std.zig.system.NativeTargetInfo.detect(artifact.target) catch unreachable;
+    const host_name = builder.host.target.zigTriple(builder.allocator) catch @panic("unhandled error");
+    const foreign_name = artifact.target.zigTriple(builder.allocator) catch @panic("unhandled error");
+    const target_info = std.zig.system.NativeTargetInfo.detect(artifact.target) catch @panic("unhandled error");
     const need_cross_glibc = artifact.target.isGnuLibC() and artifact.is_linking_libc;
     switch (builder.host.getExternalExecutor(target_info, .{
         .qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null,
lib/std/Build/FmtStep.zig
@@ -9,12 +9,12 @@ builder: *std.Build,
 argv: [][]const u8,
 
 pub fn create(builder: *std.Build, paths: []const []const u8) *FmtStep {
-    const self = builder.allocator.create(FmtStep) catch unreachable;
+    const self = builder.allocator.create(FmtStep) catch @panic("OOM");
     const name = "zig fmt";
     self.* = FmtStep{
         .step = Step.init(.fmt, name, builder.allocator, make),
         .builder = builder,
-        .argv = builder.allocator.alloc([]u8, paths.len + 2) catch unreachable,
+        .argv = builder.allocator.alloc([]u8, paths.len + 2) catch @panic("OOM"),
     };
 
     self.argv[0] = builder.zig_exe;
lib/std/Build/InstallArtifactStep.zig
@@ -16,7 +16,7 @@ h_dir: ?InstallDir,
 pub fn create(builder: *std.Build, artifact: *CompileStep) *InstallArtifactStep {
     if (artifact.install_step) |s| return s;
 
-    const self = builder.allocator.create(InstallArtifactStep) catch unreachable;
+    const self = builder.allocator.create(InstallArtifactStep) catch @panic("OOM");
     self.* = InstallArtifactStep{
         .builder = builder,
         .step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make),
lib/std/Build/InstallRawStep.zig
@@ -44,7 +44,7 @@ pub fn create(
     dest_filename: []const u8,
     options: CreateOptions,
 ) *InstallRawStep {
-    const self = builder.allocator.create(InstallRawStep) catch unreachable;
+    const self = builder.allocator.create(InstallRawStep) catch @panic("OOM");
     self.* = InstallRawStep{
         .step = Step.init(.install_raw, builder.fmt("install raw binary {s}", .{artifact.step.name}), builder.allocator, make),
         .builder = builder,
@@ -82,7 +82,7 @@ fn make(step: *Step) !void {
     const full_dest_path = b.getInstallPath(self.dest_dir, self.dest_filename);
     self.output_file.path = full_dest_path;
 
-    fs.cwd().makePath(b.getInstallPath(self.dest_dir, "")) catch unreachable;
+    try fs.cwd().makePath(b.getInstallPath(self.dest_dir, ""));
 
     var argv_list = std.ArrayList([]const u8).init(b.allocator);
     try argv_list.appendSlice(&.{ b.zig_exe, "objcopy" });
lib/std/Build/OptionsStep.zig
@@ -19,7 +19,7 @@ artifact_args: std.ArrayList(OptionArtifactArg),
 file_source_args: std.ArrayList(OptionFileSourceArg),
 
 pub fn create(builder: *std.Build) *OptionsStep {
-    const self = builder.allocator.create(OptionsStep) catch unreachable;
+    const self = builder.allocator.create(OptionsStep) catch @panic("OOM");
     self.* = .{
         .builder = builder,
         .step = Step.init(.options, "options", builder.allocator, make),
@@ -34,44 +34,48 @@ pub fn create(builder: *std.Build) *OptionsStep {
 }
 
 pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: T) void {
+    return addOptionFallible(self, T, name, value) catch @panic("unhandled error");
+}
+
+fn addOptionFallible(self: *OptionsStep, comptime T: type, name: []const u8, value: T) !void {
     const out = self.contents.writer();
     switch (T) {
         []const []const u8 => {
-            out.print("pub const {}: []const []const u8 = &[_][]const u8{{\n", .{std.zig.fmtId(name)}) catch unreachable;
+            try out.print("pub const {}: []const []const u8 = &[_][]const u8{{\n", .{std.zig.fmtId(name)});
             for (value) |slice| {
-                out.print("    \"{}\",\n", .{std.zig.fmtEscapes(slice)}) catch unreachable;
+                try out.print("    \"{}\",\n", .{std.zig.fmtEscapes(slice)});
             }
-            out.writeAll("};\n") catch unreachable;
+            try out.writeAll("};\n");
             return;
         },
         [:0]const u8 => {
-            out.print("pub const {}: [:0]const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) }) catch unreachable;
+            try out.print("pub const {}: [:0]const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) });
             return;
         },
         []const u8 => {
-            out.print("pub const {}: []const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) }) catch unreachable;
+            try out.print("pub const {}: []const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) });
             return;
         },
         ?[:0]const u8 => {
-            out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(name)}) catch unreachable;
+            try out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(name)});
             if (value) |payload| {
-                out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)}) catch unreachable;
+                try out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)});
             } else {
-                out.writeAll("null;\n") catch unreachable;
+                try out.writeAll("null;\n");
             }
             return;
         },
         ?[]const u8 => {
-            out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(name)}) catch unreachable;
+            try out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(name)});
             if (value) |payload| {
-                out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)}) catch unreachable;
+                try out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)});
             } else {
-                out.writeAll("null;\n") catch unreachable;
+                try out.writeAll("null;\n");
             }
             return;
         },
         std.builtin.Version => {
-            out.print(
+            try out.print(
                 \\pub const {}: @import("std").builtin.Version = .{{
                 \\    .major = {d},
                 \\    .minor = {d},
@@ -84,11 +88,11 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value:
                 value.major,
                 value.minor,
                 value.patch,
-            }) catch unreachable;
+            });
             return;
         },
         std.SemanticVersion => {
-            out.print(
+            try out.print(
                 \\pub const {}: @import("std").SemanticVersion = .{{
                 \\    .major = {d},
                 \\    .minor = {d},
@@ -100,38 +104,38 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value:
                 value.major,
                 value.minor,
                 value.patch,
-            }) catch unreachable;
+            });
             if (value.pre) |some| {
-                out.print("    .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)}) catch unreachable;
+                try out.print("    .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});
             }
             if (value.build) |some| {
-                out.print("    .build = \"{}\",\n", .{std.zig.fmtEscapes(some)}) catch unreachable;
+                try out.print("    .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});
             }
-            out.writeAll("};\n") catch unreachable;
+            try out.writeAll("};\n");
             return;
         },
         else => {},
     }
     switch (@typeInfo(T)) {
         .Enum => |enum_info| {
-            out.print("pub const {} = enum {{\n", .{std.zig.fmtId(@typeName(T))}) catch unreachable;
+            try out.print("pub const {} = enum {{\n", .{std.zig.fmtId(@typeName(T))});
             inline for (enum_info.fields) |field| {
-                out.print("    {},\n", .{std.zig.fmtId(field.name)}) catch unreachable;
+                try out.print("    {},\n", .{std.zig.fmtId(field.name)});
             }
-            out.writeAll("};\n") catch unreachable;
-            out.print("pub const {}: {s} = {s}.{s};\n", .{
+            try out.writeAll("};\n");
+            try out.print("pub const {}: {s} = {s}.{s};\n", .{
                 std.zig.fmtId(name),
                 std.zig.fmtId(@typeName(T)),
                 std.zig.fmtId(@typeName(T)),
                 std.zig.fmtId(@tagName(value)),
-            }) catch unreachable;
+            });
             return;
         },
         else => {},
     }
-    out.print("pub const {}: {s} = ", .{ std.zig.fmtId(name), @typeName(T) }) catch unreachable;
-    printLiteral(out, value, 0) catch unreachable;
-    out.writeAll(";\n") catch unreachable;
+    try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(name), @typeName(T) });
+    try printLiteral(out, value, 0);
+    try out.writeAll(";\n");
 }
 
 // TODO: non-recursive?
@@ -189,14 +193,14 @@ pub fn addOptionFileSource(
     self.file_source_args.append(.{
         .name = name,
         .source = source.dupe(self.builder),
-    }) catch unreachable;
+    }) catch @panic("OOM");
     source.addStepDependencies(&self.step);
 }
 
 /// The value is the path in the cache dir.
 /// Adds a dependency automatically.
 pub fn addOptionArtifact(self: *OptionsStep, name: []const u8, artifact: *CompileStep) void {
-    self.artifact_args.append(.{ .name = self.builder.dupe(name), .artifact = artifact }) catch unreachable;
+    self.artifact_args.append(.{ .name = self.builder.dupe(name), .artifact = artifact }) catch @panic("OOM");
     self.step.dependOn(&artifact.step);
 }
 
lib/std/Build/RunStep.zig
@@ -54,7 +54,7 @@ pub const Arg = union(enum) {
 };
 
 pub fn create(builder: *std.Build, name: []const u8) *RunStep {
-    const self = builder.allocator.create(RunStep) catch unreachable;
+    const self = builder.allocator.create(RunStep) catch @panic("OOM");
     self.* = RunStep{
         .builder = builder,
         .step = Step.init(base_id, name, builder.allocator, make),
@@ -67,19 +67,19 @@ pub fn create(builder: *std.Build, name: []const u8) *RunStep {
 }
 
 pub fn addArtifactArg(self: *RunStep, artifact: *CompileStep) void {
-    self.argv.append(Arg{ .artifact = artifact }) catch unreachable;
+    self.argv.append(Arg{ .artifact = artifact }) catch @panic("OOM");
     self.step.dependOn(&artifact.step);
 }
 
 pub fn addFileSourceArg(self: *RunStep, file_source: std.Build.FileSource) void {
     self.argv.append(Arg{
         .file_source = file_source.dupe(self.builder),
-    }) catch unreachable;
+    }) catch @panic("OOM");
     file_source.addStepDependencies(&self.step);
 }
 
 pub fn addArg(self: *RunStep, arg: []const u8) void {
-    self.argv.append(Arg{ .bytes = self.builder.dupe(arg) }) catch unreachable;
+    self.argv.append(Arg{ .bytes = self.builder.dupe(arg) }) catch @panic("OOM");
 }
 
 pub fn addArgs(self: *RunStep, args: []const []const u8) void {
@@ -89,7 +89,7 @@ pub fn addArgs(self: *RunStep, args: []const []const u8) void {
 }
 
 pub fn clearEnvironment(self: *RunStep) void {
-    const new_env_map = self.builder.allocator.create(EnvMap) catch unreachable;
+    const new_env_map = self.builder.allocator.create(EnvMap) catch @panic("OOM");
     new_env_map.* = EnvMap.init(self.builder.allocator);
     self.env_map = new_env_map;
 }
@@ -107,9 +107,9 @@ pub fn addPathDirInternal(step: *Step, builder: *std.Build, search_path: []const
 
     if (prev_path) |pp| {
         const new_path = builder.fmt("{s}" ++ [1]u8{fs.path.delimiter} ++ "{s}", .{ pp, search_path });
-        env_map.put(key, new_path) catch unreachable;
+        env_map.put(key, new_path) catch @panic("OOM");
     } else {
-        env_map.put(key, builder.dupePath(search_path)) catch unreachable;
+        env_map.put(key, builder.dupePath(search_path)) catch @panic("OOM");
     }
 }
 
@@ -124,8 +124,8 @@ fn getEnvMapInternal(step: *Step, allocator: Allocator) *EnvMap {
         else => unreachable,
     };
     return maybe_env_map orelse {
-        const env_map = allocator.create(EnvMap) catch unreachable;
-        env_map.* = process.getEnvMap(allocator) catch unreachable;
+        const env_map = allocator.create(EnvMap) catch @panic("OOM");
+        env_map.* = process.getEnvMap(allocator) catch @panic("unhandled error");
         switch (step.id) {
             .run => step.cast(RunStep).?.env_map = env_map,
             .emulatable_run => step.cast(RunStep).?.env_map = env_map,
@@ -140,7 +140,7 @@ pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8
     env_map.put(
         self.builder.dupe(key),
         self.builder.dupe(value),
-    ) catch unreachable;
+    ) catch @panic("unhandled error");
 }
 
 pub fn expectStdErrEqual(self: *RunStep, bytes: []const u8) void {
@@ -234,7 +234,7 @@ pub fn runCommand(
 
     switch (stdout_action) {
         .expect_exact, .expect_matches => {
-            stdout = child.stdout.?.reader().readAllAlloc(builder.allocator, max_stdout_size) catch unreachable;
+            stdout = try child.stdout.?.reader().readAllAlloc(builder.allocator, max_stdout_size);
         },
         .inherit, .ignore => {},
     }
@@ -244,7 +244,7 @@ pub fn runCommand(
 
     switch (stderr_action) {
         .expect_exact, .expect_matches => {
-            stderr = child.stderr.?.reader().readAllAlloc(builder.allocator, max_stdout_size) catch unreachable;
+            stderr = try child.stderr.?.reader().readAllAlloc(builder.allocator, max_stdout_size);
         },
         .inherit, .ignore => {},
     }
lib/std/Build/Step.zig
@@ -57,7 +57,7 @@ pub fn init(
 ) Step {
     return Step{
         .id = id,
-        .name = allocator.dupe(u8, name) catch unreachable,
+        .name = allocator.dupe(u8, name) catch @panic("OOM"),
         .makeFn = makeFn,
         .dependencies = std.ArrayList(*Step).init(allocator),
         .loop_flag = false,
@@ -77,7 +77,7 @@ pub fn make(self: *Step) !void {
 }
 
 pub fn dependOn(self: *Step, other: *Step) void {
-    self.dependencies.append(other) catch unreachable;
+    self.dependencies.append(other) catch @panic("OOM");
 }
 
 fn makeNoOp(self: *Step) anyerror!void {
lib/std/Build/TranslateCStep.zig
@@ -28,7 +28,7 @@ pub const Options = struct {
 };
 
 pub fn create(builder: *std.Build, options: Options) *TranslateCStep {
-    const self = builder.allocator.create(TranslateCStep) catch unreachable;
+    const self = builder.allocator.create(TranslateCStep) catch @panic("OOM");
     const source = options.source_file.dupe(builder);
     self.* = TranslateCStep{
         .step = Step.init(.translate_c, "translate-c", builder.allocator, make),
@@ -67,7 +67,7 @@ pub fn addExecutable(self: *TranslateCStep, options: AddExecutableOptions) *Comp
 }
 
 pub fn addIncludeDir(self: *TranslateCStep, include_dir: []const u8) void {
-    self.include_dirs.append(self.builder.dupePath(include_dir)) catch unreachable;
+    self.include_dirs.append(self.builder.dupePath(include_dir)) catch @panic("OOM");
 }
 
 pub fn addCheckFile(self: *TranslateCStep, expected_matches: []const []const u8) *CheckFileStep {
@@ -78,12 +78,12 @@ pub fn addCheckFile(self: *TranslateCStep, expected_matches: []const []const u8)
 /// `name` and `value` need not live longer than the function call.
 pub fn defineCMacro(self: *TranslateCStep, name: []const u8, value: ?[]const u8) void {
     const macro = std.Build.constructCMacro(self.builder.allocator, name, value);
-    self.c_macros.append(macro) catch unreachable;
+    self.c_macros.append(macro) catch @panic("OOM");
 }
 
 /// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1.
 pub fn defineCMacroRaw(self: *TranslateCStep, name_and_value: []const u8) void {
-    self.c_macros.append(self.builder.dupe(name_and_value)) catch unreachable;
+    self.c_macros.append(self.builder.dupe(name_and_value)) catch @panic("OOM");
 }
 
 fn make(step: *Step) !void {
@@ -129,8 +129,8 @@ fn make(step: *Step) !void {
         self.output_dir = fs.path.dirname(output_path).?;
     }
 
-    self.output_file.path = fs.path.join(
+    self.output_file.path = try fs.path.join(
         self.builder.allocator,
         &[_][]const u8{ self.output_dir.?, self.out_basename },
-    ) catch unreachable;
+    );
 }
lib/std/Build/WriteFileStep.zig
@@ -28,7 +28,7 @@ pub fn init(builder: *std.Build) WriteFileStep {
 }
 
 pub fn add(self: *WriteFileStep, basename: []const u8, bytes: []const u8) void {
-    const node = self.builder.allocator.create(std.TailQueue(File).Node) catch unreachable;
+    const node = self.builder.allocator.create(std.TailQueue(File).Node) catch @panic("unhandled error");
     node.* = .{
         .data = .{
             .source = std.Build.GeneratedFile{ .step = &self.step },
@@ -106,10 +106,10 @@ fn make(step: *Step) !void {
                 });
                 return err;
             };
-            node.data.source.path = fs.path.join(
+            node.data.source.path = try fs.path.join(
                 self.builder.allocator,
                 &[_][]const u8{ self.output_dir, node.data.basename },
-            ) catch unreachable;
+            );
         }
     }
 }
lib/std/Build.zig
@@ -564,12 +564,12 @@ pub fn addConfigHeader(
 
 /// Allocator.dupe without the need to handle out of memory.
 pub fn dupe(self: *Build, bytes: []const u8) []u8 {
-    return self.allocator.dupe(u8, bytes) catch unreachable;
+    return self.allocator.dupe(u8, bytes) catch @panic("OOM");
 }
 
 /// Duplicates an array of strings without the need to handle out of memory.
 pub fn dupeStrings(self: *Build, strings: []const []const u8) [][]u8 {
-    const array = self.allocator.alloc([]u8, strings.len) catch unreachable;
+    const array = self.allocator.alloc([]u8, strings.len) catch @panic("OOM");
     for (strings) |s, i| {
         array[i] = self.dupe(s);
     }
@@ -596,7 +596,7 @@ pub fn dupePkg(self: *Build, package: Pkg) Pkg {
     };
 
     if (package.dependencies) |dependencies| {
-        const new_dependencies = self.allocator.alloc(Pkg, dependencies.len) catch unreachable;
+        const new_dependencies = self.allocator.alloc(Pkg, dependencies.len) catch @panic("OOM");
         the_copy.dependencies = new_dependencies;
 
         for (dependencies) |dep_package, i| {
@@ -613,20 +613,20 @@ pub fn addWriteFile(self: *Build, file_path: []const u8, data: []const u8) *Writ
 }
 
 pub fn addWriteFiles(self: *Build) *WriteFileStep {
-    const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
+    const write_file_step = self.allocator.create(WriteFileStep) catch @panic("OOM");
     write_file_step.* = WriteFileStep.init(self);
     return write_file_step;
 }
 
 pub fn addLog(self: *Build, comptime format: []const u8, args: anytype) *LogStep {
     const data = self.fmt(format, args);
-    const log_step = self.allocator.create(LogStep) catch unreachable;
+    const log_step = self.allocator.create(LogStep) catch @panic("OOM");
     log_step.* = LogStep.init(self, data);
     return log_step;
 }
 
 pub fn addRemoveDirTree(self: *Build, dir_path: []const u8) *RemoveDirStep {
-    const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
+    const remove_dir_step = self.allocator.create(RemoveDirStep) catch @panic("OOM");
     remove_dir_step.* = RemoveDirStep.init(self, dir_path);
     return remove_dir_step;
 }
@@ -719,13 +719,13 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
     const type_id = comptime typeToEnum(T);
     const enum_options = if (type_id == .@"enum") blk: {
         const fields = comptime std.meta.fields(T);
-        var options = ArrayList([]const u8).initCapacity(self.allocator, fields.len) catch unreachable;
+        var options = ArrayList([]const u8).initCapacity(self.allocator, fields.len) catch @panic("OOM");
 
         inline for (fields) |field| {
             options.appendAssumeCapacity(field.name);
         }
 
-        break :blk options.toOwnedSlice() catch unreachable;
+        break :blk options.toOwnedSlice() catch @panic("OOM");
     } else null;
     const available_option = AvailableOption{
         .name = name,
@@ -733,10 +733,10 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
         .description = description,
         .enum_options = enum_options,
     };
-    if ((self.available_options_map.fetchPut(name, available_option) catch unreachable) != null) {
+    if ((self.available_options_map.fetchPut(name, available_option) catch @panic("OOM")) != null) {
         panic("Option '{s}' declared twice", .{name});
     }
-    self.available_options_list.append(available_option) catch unreachable;
+    self.available_options_list.append(available_option) catch @panic("OOM");
 
     const option_ptr = self.user_input_options.getPtr(name) orelse return null;
     option_ptr.used = true;
@@ -840,7 +840,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
                 return null;
             },
             .scalar => |s| {
-                return self.allocator.dupe([]const u8, &[_][]const u8{s}) catch unreachable;
+                return self.allocator.dupe([]const u8, &[_][]const u8{s}) catch @panic("OOM");
             },
             .list => |lst| return lst.items,
         },
@@ -848,12 +848,12 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_
 }
 
 pub fn step(self: *Build, name: []const u8, description: []const u8) *Step {
-    const step_info = self.allocator.create(TopLevelStep) catch unreachable;
+    const step_info = self.allocator.create(TopLevelStep) catch @panic("OOM");
     step_info.* = TopLevelStep{
         .step = Step.initNoOp(.top_level, name, self.allocator),
         .description = self.dupe(description),
     };
-    self.top_level_steps.append(step_info) catch unreachable;
+    self.top_level_steps.append(step_info) catch @panic("OOM");
     return &step_info.step;
 }
 
@@ -949,7 +949,7 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros
         },
     };
 
-    const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch unreachable;
+    const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch @panic("OOM");
 
     if (args.whitelist) |list| whitelist_check: {
         // Make sure it's a match of one of the list.
@@ -960,7 +960,7 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros
             mismatch_cpu_features = true;
             mismatch_triple = true;
 
-            const t_triple = t.zigTriple(self.allocator) catch unreachable;
+            const t_triple = t.zigTriple(self.allocator) catch @panic("OOM");
             if (mem.eql(u8, t_triple, selected_canonicalized_triple)) {
                 mismatch_triple = false;
                 whitelist_item = t;
@@ -977,7 +977,7 @@ pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) Cros
                 selected_canonicalized_triple,
             });
             for (list) |t| {
-                const t_triple = t.zigTriple(self.allocator) catch unreachable;
+                const t_triple = t.zigTriple(self.allocator) catch @panic("OOM");
                 log.err(" {s}", .{t_triple});
             }
         } else {
@@ -1033,22 +1033,22 @@ pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const
         .scalar => |s| {
             // turn it into a list
             var list = ArrayList([]const u8).init(self.allocator);
-            list.append(s) catch unreachable;
-            list.append(value) catch unreachable;
-            self.user_input_options.put(name, .{
+            try list.append(s);
+            try list.append(value);
+            try self.user_input_options.put(name, .{
                 .name = name,
                 .value = .{ .list = list },
                 .used = false,
-            }) catch unreachable;
+            });
         },
         .list => |*list| {
             // append to the list
-            list.append(value) catch unreachable;
-            self.user_input_options.put(name, .{
+            try list.append(value);
+            try self.user_input_options.put(name, .{
                 .name = name,
                 .value = .{ .list = list.* },
                 .used = false,
-            }) catch unreachable;
+            });
         },
         .flag => {
             log.warn("Option '-D{s}={s}' conflicts with flag '-D{s}'.", .{ name, value, name });
@@ -1240,13 +1240,13 @@ pub fn addInstallFileWithDir(
     if (dest_rel_path.len == 0) {
         panic("dest_rel_path must be non-empty", .{});
     }
-    const install_step = self.allocator.create(InstallFileStep) catch unreachable;
+    const install_step = self.allocator.create(InstallFileStep) catch @panic("OOM");
     install_step.* = InstallFileStep.init(self, source.dupe(self), install_dir, dest_rel_path);
     return install_step;
 }
 
 pub fn addInstallDirectory(self: *Build, options: InstallDirectoryOptions) *InstallDirStep {
-    const install_step = self.allocator.create(InstallDirStep) catch unreachable;
+    const install_step = self.allocator.create(InstallDirStep) catch @panic("OOM");
     install_step.* = InstallDirStep.init(self, options);
     return install_step;
 }
@@ -1256,7 +1256,7 @@ pub fn pushInstalledFile(self: *Build, dir: InstallDir, dest_rel_path: []const u
         .dir = dir,
         .path = dest_rel_path,
     };
-    self.installed_files.append(file.dupe(self)) catch unreachable;
+    self.installed_files.append(file.dupe(self)) catch @panic("OOM");
 }
 
 pub fn updateFile(self: *Build, source_path: []const u8, dest_path: []const u8) !void {
@@ -1289,16 +1289,15 @@ pub fn truncateFile(self: *Build, dest_path: []const u8) !void {
 }
 
 pub fn pathFromRoot(self: *Build, rel_path: []const u8) []u8 {
-    return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch unreachable;
+    return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch @panic("OOM");
 }
 
-/// Shorthand for `std.fs.path.join(Build.allocator, paths) catch unreachable`
 pub fn pathJoin(self: *Build, paths: []const []const u8) []u8 {
-    return fs.path.join(self.allocator, paths) catch unreachable;
+    return fs.path.join(self.allocator, paths) catch @panic("OOM");
 }
 
 pub fn fmt(self: *Build, comptime format: []const u8, args: anytype) []u8 {
-    return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable;
+    return fmt_lib.allocPrint(self.allocator, format, args) catch @panic("OOM");
 }
 
 pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 {
@@ -1442,7 +1441,7 @@ pub fn exec(self: *Build, argv: []const []const u8) ![]u8 {
 }
 
 pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void {
-    self.search_prefixes.append(self.dupePath(search_prefix)) catch unreachable;
+    self.search_prefixes.append(self.dupePath(search_prefix)) catch @panic("OOM");
 }
 
 pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
@@ -1457,7 +1456,7 @@ pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8)
     return fs.path.resolve(
         self.allocator,
         &[_][]const u8{ base_dir, dest_rel_path },
-    ) catch unreachable;
+    ) catch @panic("OOM");
 }
 
 pub const Dependency = struct {
@@ -1509,14 +1508,14 @@ fn dependencyInner(
     comptime build_zig: type,
     args: anytype,
 ) *Dependency {
-    const sub_builder = b.createChild(name, build_root, args) catch unreachable;
-    sub_builder.runBuild(build_zig) catch unreachable;
+    const sub_builder = b.createChild(name, build_root, args) catch @panic("unhandled error");
+    sub_builder.runBuild(build_zig) catch @panic("unhandled error");
 
     if (sub_builder.validateUserInputDidItFail()) {
         std.debug.dumpCurrentStackTrace(@returnAddress());
     }
 
-    const dep = b.allocator.create(Dependency) catch unreachable;
+    const dep = b.allocator.create(Dependency) catch @panic("OOM");
     dep.* = .{ .builder = sub_builder };
     return dep;
 }