aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-02-08 02:08:45 -0500
committerAndrew Kelley <superjoe30@gmail.com>2018-02-08 02:08:45 -0500
commit0d5ff6f4622a492dddbb1fc2b19b3157237500b1 (patch)
tree4a707f626dc12adeeed3438b5966876c6b401ea0 /std
parent68238d5678a4c055bb6f1206254dcac2e0c634f0 (diff)
downloadzig-0d5ff6f4622a492dddbb1fc2b19b3157237500b1.tar.gz
zig-0d5ff6f4622a492dddbb1fc2b19b3157237500b1.zip
error sets - most tests passing
Diffstat (limited to 'std')
-rw-r--r--std/build.zig8
-rw-r--r--std/fmt/index.zig2
-rw-r--r--std/io.zig4
-rw-r--r--std/os/child_process.zig21
-rw-r--r--std/os/index.zig99
-rw-r--r--std/os/windows/util.zig3
-rw-r--r--std/special/bootstrap.zig4
-rw-r--r--std/special/build_runner.zig25
8 files changed, 127 insertions, 39 deletions
diff --git a/std/build.zig b/std/build.zig
index 216699f355..ee1990a349 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -271,7 +271,7 @@ pub const Builder = struct {
return &self.uninstall_tls.step;
}
- fn makeUninstall(uninstall_step: &Step) !void {
+ fn makeUninstall(uninstall_step: &Step) error!void {
const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step);
const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls);
@@ -285,7 +285,7 @@ pub const Builder = struct {
// TODO remove empty directories
}
- fn makeOneStep(self: &Builder, s: &Step) !void {
+ fn makeOneStep(self: &Builder, s: &Step) error!void {
if (s.loop_flag) {
warn("Dependency loop detected:\n {}\n", s.name);
return error.DependencyLoopDetected;
@@ -1910,7 +1910,7 @@ pub const LogStep = struct {
};
}
- fn make(step: &Step) !void {
+ fn make(step: &Step) error!void {
const self = @fieldParentPtr(LogStep, "step", step);
warn("{}", self.data);
}
@@ -1972,7 +1972,7 @@ pub const Step = struct {
self.dependencies.append(other) catch unreachable;
}
- fn makeNoOp(self: &Step) (error{}!void) {}
+ fn makeNoOp(self: &Step) error!void {}
};
fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index 407ffd901b..98f8d3d26b 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -510,7 +510,7 @@ pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...
return bufPrint(buf, fmt, args);
}
-fn countSize(size: &usize, bytes: []const u8) !void {
+fn countSize(size: &usize, bytes: []const u8) (error{}!void) {
*size += bytes.len;
}
diff --git a/std/io.zig b/std/io.zig
index 842c30a0e4..9f16c5f496 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -694,13 +694,13 @@ pub const BufferOutStream = struct {
pub fn init(buffer: &Buffer) BufferOutStream {
return BufferOutStream {
.buffer = buffer,
- .stream = OutStream {
+ .stream = Stream {
.writeFn = writeFn,
},
};
}
- fn writeFn(out_stream: &OutStream, bytes: []const u8) !void {
+ fn writeFn(out_stream: &Stream, bytes: []const u8) !void {
const self = @fieldParentPtr(BufferOutStream, "stream", out_stream);
return self.buffer.append(bytes);
}
diff --git a/std/os/child_process.zig b/std/os/child_process.zig
index 360a1bfb93..1b7639fb71 100644
--- a/std/os/child_process.zig
+++ b/std/os/child_process.zig
@@ -55,7 +55,22 @@ pub const ChildProcess = struct {
llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
pub const SpawnError = error {
-
+ ProcessFdQuotaExceeded,
+ Unexpected,
+ NotDir,
+ SystemResources,
+ FileNotFound,
+ NameTooLong,
+ SymLinkLoop,
+ FileSystem,
+ OutOfMemory,
+ AccessDenied,
+ PermissionDenied,
+ InvalidUserId,
+ ResourceLimitReached,
+ InvalidExe,
+ IsDir,
+ FileBusy,
};
pub const Term = union(enum) {
@@ -313,7 +328,7 @@ pub const ChildProcess = struct {
// Here we potentially return the fork child's error
// from the parent pid.
if (err_int != @maxValue(ErrInt)) {
- return error(err_int);
+ return SpawnError(err_int);
}
return statusToTerm(status);
@@ -757,7 +772,7 @@ fn destroyPipe(pipe: &const [2]i32) void {
// Child of fork calls this to report an error to the fork parent.
// Then the child exits.
-fn forkChildErrReport(fd: i32, err: error) noreturn {
+fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
_ = writeIntFd(fd, ErrInt(err));
posix.exit(1);
}
diff --git a/std/os/index.zig b/std/os/index.zig
index 33707676bb..c5191c8d74 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -243,7 +243,6 @@ pub const PosixOpenError = error {
SystemResources,
NoSpaceLeft,
NotDir,
- AccessDenied,
PathAlreadyExists,
Unexpected,
};
@@ -411,7 +410,19 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap,
return posixExecveErrnoToErr(err);
}
-fn posixExecveErrnoToErr(err: usize) error {
+pub const PosixExecveError = error {
+ SystemResources,
+ AccessDenied,
+ InvalidExe,
+ FileSystem,
+ IsDir,
+ FileNotFound,
+ NotDir,
+ FileBusy,
+ Unexpected,
+};
+
+fn posixExecveErrnoToErr(err: usize) PosixExecveError {
assert(err > 0);
return switch (err) {
posix.EFAULT => unreachable,
@@ -904,24 +915,68 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void {
/// removes it. If it cannot be removed because it is a non-empty directory,
/// this function recursively removes its entries and then tries again.
// TODO non-recursive implementation
-pub fn deleteTree(allocator: &Allocator, full_path: []const u8) !void {
+const DeleteTreeError = error {
+ OutOfMemory,
+ AccessDenied,
+ FileTooBig,
+ IsDir,
+ SymLinkLoop,
+ ProcessFdQuotaExceeded,
+ NameTooLong,
+ SystemFdQuotaExceeded,
+ NoDevice,
+ PathNotFound,
+ SystemResources,
+ NoSpaceLeft,
+ PathAlreadyExists,
+ ReadOnlyFileSystem,
+ NotDir,
+ FileNotFound,
+ FileSystem,
+ FileBusy,
+ DirNotEmpty,
+ Unexpected,
+};
+pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError!void {
start_over: while (true) {
// First, try deleting the item as a file. This way we don't follow sym links.
if (deleteFile(allocator, full_path)) {
return;
- } else |err| {
- if (err == error.FileNotFound)
- return;
- if (err != error.IsDir)
- return err;
+ } else |err| switch (err) {
+ error.FileNotFound => return,
+ error.IsDir => {},
+
+ error.OutOfMemory,
+ error.AccessDenied,
+ error.SymLinkLoop,
+ error.NameTooLong,
+ error.SystemResources,
+ error.ReadOnlyFileSystem,
+ error.NotDir,
+ error.FileSystem,
+ error.FileBusy,
+ error.Unexpected
+ => return err,
}
{
- var dir = Dir.open(allocator, full_path) catch |err| {
- if (err == error.FileNotFound)
- return;
- if (err == error.NotDir)
- continue :start_over;
- return err;
+ var dir = Dir.open(allocator, full_path) catch |err| switch (err) {
+ error.NotDir => continue :start_over,
+
+ error.OutOfMemory,
+ error.AccessDenied,
+ error.FileTooBig,
+ error.IsDir,
+ error.SymLinkLoop,
+ error.ProcessFdQuotaExceeded,
+ error.NameTooLong,
+ error.SystemFdQuotaExceeded,
+ error.NoDevice,
+ error.PathNotFound,
+ error.SystemResources,
+ error.NoSpaceLeft,
+ error.PathAlreadyExists,
+ error.Unexpected
+ => return err,
};
defer dir.close();
@@ -1252,6 +1307,8 @@ pub const ArgIteratorWindows = struct {
quote_count: usize,
seen_quote_count: usize,
+ pub const NextError = error{OutOfMemory};
+
pub fn init() ArgIteratorWindows {
return initWithCmdLine(windows.GetCommandLineA());
}
@@ -1267,7 +1324,7 @@ pub const ArgIteratorWindows = struct {
}
/// You must free the returned memory when done.
- pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?(@typeOf(internalNext).ReturnType.ErrorSet![]u8) {
+ pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?(NextError![]u8) {
// march forward over whitespace
while (true) : (self.index += 1) {
const byte = self.cmd_line[self.index];
@@ -1320,7 +1377,7 @@ pub const ArgIteratorWindows = struct {
}
}
- fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) ![]u8 {
+ fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) NextError![]u8 {
var buf = try Buffer.initSize(allocator, 0);
defer buf.deinit();
@@ -1394,16 +1451,20 @@ pub const ArgIteratorWindows = struct {
};
pub const ArgIterator = struct {
- inner: if (builtin.os == Os.windows) ArgIteratorWindows else ArgIteratorPosix,
+ const InnerType = if (builtin.os == Os.windows) ArgIteratorWindows else ArgIteratorPosix;
+
+ inner: InnerType,
pub fn init() ArgIterator {
return ArgIterator {
- .inner = if (builtin.os == Os.windows) ArgIteratorWindows.init() else ArgIteratorPosix.init(),
+ .inner = InnerType.init(),
};
}
+
+ pub const NextError = ArgIteratorWindows.NextError;
/// You must free the returned memory when done.
- pub fn next(self: &ArgIterator, allocator: &Allocator) ?![]u8 {
+ pub fn next(self: &ArgIterator, allocator: &Allocator) ?(NextError![]u8) {
if (builtin.os == Os.windows) {
return self.inner.next(allocator);
} else {
diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig
index 2569763489..e2d7c14149 100644
--- a/std/os/windows/util.zig
+++ b/std/os/windows/util.zig
@@ -30,7 +30,6 @@ pub fn windowsClose(handle: windows.HANDLE) void {
pub const WriteError = error {
SystemResources,
OperationAborted,
- SystemResources,
IoPending,
BrokenPipe,
Unexpected,
@@ -83,6 +82,8 @@ pub const OpenError = error {
AccessDenied,
PipeBusy,
Unexpected,
+ OutOfMemory,
+ NameTooLong,
};
/// `file_path` may need to be copied in memory to add a null terminating byte. In this case
diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig
index bcb3456353..f5754638b0 100644
--- a/std/special/bootstrap.zig
+++ b/std/special/bootstrap.zig
@@ -77,7 +77,7 @@ fn callMain() u8 {
},
builtin.TypeId.Int => {
if (@typeOf(root.main).ReturnType.bit_count != 8) {
- @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '%void'");
+ @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");
}
return root.main();
},
@@ -91,6 +91,6 @@ fn callMain() u8 {
};
return 0;
},
- else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"),
+ else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),
}
}
diff --git a/std/special/build_runner.zig b/std/special/build_runner.zig
index 198199b941..0661d26a98 100644
--- a/std/special/build_runner.zig
+++ b/std/special/build_runner.zig
@@ -1,5 +1,6 @@
const root = @import("@build");
const std = @import("std");
+const builtin = @import("builtin");
const io = std.io;
const fmt = std.fmt;
const os = std.os;
@@ -43,14 +44,14 @@ pub fn main() !void {
var stderr_file = io.getStdErr();
var stderr_file_stream: io.FileOutStream = undefined;
- var stderr_stream: %&io.OutStream = if (stderr_file) |*f| x: {
+ var stderr_stream = if (stderr_file) |*f| x: {
stderr_file_stream = io.FileOutStream.init(f);
break :x &stderr_file_stream.stream;
} else |err| err;
var stdout_file = io.getStdOut();
var stdout_file_stream: io.FileOutStream = undefined;
- var stdout_stream: %&io.OutStream = if (stdout_file) |*f| x: {
+ var stdout_stream = if (stdout_file) |*f| x: {
stdout_file_stream = io.FileOutStream.init(f);
break :x &stdout_file_stream.stream;
} else |err| err;
@@ -110,7 +111,7 @@ pub fn main() !void {
}
builder.setInstallPrefix(prefix);
- try root.build(&builder);
+ try runBuild(&builder);
if (builder.validateUserInputDidItFail())
return usageAndErr(&builder, true, try stderr_stream);
@@ -123,11 +124,19 @@ pub fn main() !void {
};
}
-fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) !void {
+fn runBuild(builder: &Builder) error!void {
+ switch (@typeId(@typeOf(root.build).ReturnType)) {
+ builtin.TypeId.Void => root.build(builder),
+ builtin.TypeId.ErrorUnion => try root.build(builder),
+ else => @compileError("expected return type of build to be 'void' or '!void'"),
+ }
+}
+
+fn usage(builder: &Builder, already_ran_build: bool, out_stream: var) !void {
// run the build script to collect the options
if (!already_ran_build) {
builder.setInstallPrefix(null);
- try root.build(builder);
+ try runBuild(builder);
}
// This usage text has to be synchronized with src/main.cpp
@@ -181,12 +190,14 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream)
);
}
-fn usageAndErr(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) error {
+fn usageAndErr(builder: &Builder, already_ran_build: bool, out_stream: var) error {
usage(builder, already_ran_build, out_stream) catch {};
return error.InvalidArgs;
}
-fn unwrapArg(arg: %[]u8) ![]u8 {
+const UnwrapArgError = error {OutOfMemory};
+
+fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 {
return arg catch |err| {
warn("Unable to parse command line: {}\n", err);
return err;