Commit 5f518dbeb9

Andrew Kelley <superjoe30@gmail.com>
2018-02-01 04:48:40
*WIP* error sets converting std lib
1 parent 5161d70
doc/docgen.zig
@@ -12,7 +12,7 @@ const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt();
 const obj_ext = std.build.Target(std.build.Target.Native).oFileExt();
 const tmp_dir_name = "docgen_tmp";
 
-pub fn main() %void {
+pub fn main() !void {
     // TODO use a more general purpose allocator here
     var inc_allocator = try std.heap.IncrementingAllocator.init(max_doc_file_size);
     defer inc_allocator.deinit();
@@ -243,13 +243,13 @@ fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const
     return error.ParseError;
 }
 
-fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) %void {
+fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) !void {
     if (token.id != id) {
         return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id));
     }
 }
 
-fn eatToken(tokenizer: &Tokenizer, id: Token.Id) %Token {
+fn eatToken(tokenizer: &Tokenizer, id: Token.Id) !Token {
     const token = tokenizer.next();
     try assertToken(tokenizer, token, id);
     return token;
@@ -316,7 +316,7 @@ const Action = enum {
     Close,
 };
 
-fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) %Toc {
+fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
     var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator);
     errdefer urls.deinit();
 
@@ -540,7 +540,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) %Toc {
     };
 }
 
-fn urlize(allocator: &mem.Allocator, input: []const u8) %[]u8 {
+fn urlize(allocator: &mem.Allocator, input: []const u8) ![]u8 {
     var buf = try std.Buffer.initSize(allocator, 0);
     defer buf.deinit();
 
@@ -560,7 +560,7 @@ fn urlize(allocator: &mem.Allocator, input: []const u8) %[]u8 {
     return buf.toOwnedSlice();
 }
 
-fn escapeHtml(allocator: &mem.Allocator, input: []const u8) %[]u8 {
+fn escapeHtml(allocator: &mem.Allocator, input: []const u8) ![]u8 {
     var buf = try std.Buffer.initSize(allocator, 0);
     defer buf.deinit();
 
@@ -604,7 +604,7 @@ test "term color" {
     assert(mem.eql(u8, result, "A<span class=\"t32\">green</span>B"));
 }
 
-fn termColor(allocator: &mem.Allocator, input: []const u8) %[]u8 {
+fn termColor(allocator: &mem.Allocator, input: []const u8) ![]u8 {
     var buf = try std.Buffer.initSize(allocator, 0);
     defer buf.deinit();
 
@@ -686,7 +686,7 @@ fn termColor(allocator: &mem.Allocator, input: []const u8) %[]u8 {
 
 error ExampleFailedToCompile;
 
-fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io.OutStream, zig_exe: []const u8) %void {
+fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io.OutStream, zig_exe: []const u8) !void {
     var code_progress_index: usize = 0;
     for (toc.nodes) |node| {
         switch (node) {
@@ -977,7 +977,7 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io
 error ChildCrashed;
 error ChildExitError;
 
-fn exec(allocator: &mem.Allocator, args: []const []const u8) %os.ChildProcess.ExecResult {
+fn exec(allocator: &mem.Allocator, args: []const []const u8) !os.ChildProcess.ExecResult {
     const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
     switch (result.term) {
         os.ChildProcess.Term.Exited => |exit_code| {
doc/langref.html.in
@@ -5598,7 +5598,9 @@ Block = option(Symbol ":") "{" many(Statement) "}"
 
 Statement = LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";"
 
-TypeExpr = PrefixOpExpression | "var"
+TypeExpr = ErrorSetExpr | "var"
+
+ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression
 
 BlockOrExpression = Block | Expression
 
@@ -5680,7 +5682,7 @@ MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression |
 
 CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
 
-MultiplyOperator = "!" | "*" | "/" | "%" | "**" | "*%"
+MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
 
 PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
 
example/cat/main.zig
@@ -5,7 +5,7 @@ const os = std.os;
 const warn = std.debug.warn;
 const allocator = std.debug.global_allocator;
 
-pub fn main() %void {
+pub fn main() !void {
     var args_it = os.args();
     const exe = try unwrapArg(??args_it.next(allocator));
     var catted_anything = false;
@@ -36,12 +36,12 @@ pub fn main() %void {
     }
 }
 
-fn usage(exe: []const u8) %void {
+fn usage(exe: []const u8) !void {
     warn("Usage: {} [FILE]...\n", exe);
     return error.Invalid;
 }
 
-fn cat_file(stdout: &io.File, file: &io.File) %void {
+fn cat_file(stdout: &io.File, file: &io.File) !void {
     var buf: [1024 * 4]u8 = undefined;
 
     while (true) {
@@ -61,7 +61,7 @@ fn cat_file(stdout: &io.File, file: &io.File) %void {
     }
 }
 
-fn unwrapArg(arg: %[]u8) %[]u8 {
+fn unwrapArg(arg: %[]u8) ![]u8 {
     return arg catch |err| {
         warn("Unable to parse command line: {}\n", err);
         return err;
example/guess_number/main.zig
@@ -5,7 +5,7 @@ const fmt = std.fmt;
 const Rand = std.rand.Rand;
 const os = std.os;
 
-pub fn main() %void {
+pub fn main() !void {
     var stdout_file = try io.getStdOut();
     var stdout_file_stream = io.FileOutStream.init(&stdout_file);
     const stdout = &stdout_file_stream.stream;
example/hello_world/hello.zig
@@ -1,6 +1,6 @@
 const std = @import("std");
 
-pub fn main() %void {
+pub fn main() !void {
     // If this program is run without stdout attached, exit with an error.
     var stdout_file = try std.io.getStdOut();
     // If this program encounters pipe failure when printing to stdout, exit
example/mix_o_files/build.zig
@@ -1,6 +1,6 @@
 const Builder = @import("std").build.Builder;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     const obj = b.addObject("base64", "base64.zig");
 
     const exe = b.addCExecutable("test");
example/shared_library/build.zig
@@ -1,6 +1,6 @@
 const Builder = @import("std").build.Builder;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
 
     const exe = b.addCExecutable("test");
src/analyze.cpp
@@ -516,6 +516,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
 
 TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *payload_type) {
     assert(err_set_type->id == TypeTableEntryIdErrorSet);
+    assert(!type_is_invalid(payload_type));
 
     TypeId type_id = {};
     type_id.id = TypeTableEntryIdErrorUnion;
@@ -1409,6 +1410,11 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
     }
 
     TypeTableEntry *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);
+    if (type_is_invalid(specified_return_type)) {
+        fn_type_id.return_type = g->builtin_types.entry_invalid;
+        return g->builtin_types.entry_invalid;
+    }
+
     if (fn_proto->auto_err_set) {
         TypeTableEntry *inferred_err_set_type = get_auto_err_set_type(g, fn_entry);
         fn_type_id.return_type = get_error_union_type(g, inferred_err_set_type, specified_return_type);
@@ -1416,10 +1422,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
         fn_type_id.return_type = specified_return_type;
     }
 
-    if (type_is_invalid(fn_type_id.return_type)) {
-        return g->builtin_types.entry_invalid;
-    }
-
     if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, fn_type_id.return_type)) {
         add_node_error(g, fn_proto->return_type,
                 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
src/parser.cpp
@@ -241,7 +241,28 @@ static Token *ast_eat_token(ParseContext *pc, size_t *token_index, TokenId token
 }
 
 /*
-TypeExpr = PrefixOpExpression | "var"
+ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression
+*/
+static AstNode *ast_parse_error_set_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
+    AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, mandatory);
+    if (!prefix_op_expr) {
+        return nullptr;
+    }
+    Token *token = &pc->tokens->at(*token_index);
+    if (token->id == TokenIdBang) {
+        *token_index += 1;
+        AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
+        node->data.bin_op_expr.op1 = prefix_op_expr;
+        node->data.bin_op_expr.bin_op = BinOpTypeErrorUnion;
+        node->data.bin_op_expr.op2 = ast_parse_prefix_op_expr(pc, token_index, true);
+        return node;
+    } else {
+        return prefix_op_expr;
+    }
+}
+
+/*
+TypeExpr = ErrorSetExpr | "var"
 */
 static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
     Token *token = &pc->tokens->at(*token_index);
@@ -250,7 +271,7 @@ static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool
         *token_index += 1;
         return node;
     } else {
-        return ast_parse_prefix_op_expr(pc, token_index, mandatory);
+        return ast_parse_error_set_expr(pc, token_index, mandatory);
     }
 }
 
@@ -2346,10 +2367,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
             node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token);
             return node;
         }
-
-        return node;
-    }
-    if (next_token->id == TokenIdBang) {
+    } else if (next_token->id == TokenIdBang) {
         *token_index += 1;
         node->data.fn_proto.auto_err_set = true;
         next_token = &pc->tokens->at(*token_index);
src-self-hosted/main.zig
@@ -20,7 +20,7 @@ error ZigInstallationNotFound;
 
 const default_zig_cache_name = "zig-cache";
 
-pub fn main() %void {
+pub fn main() !void {
     main2() catch |err| {
         if (err != error.InvalidCommandLineArguments) {
             warn("{}\n", @errorName(err));
@@ -48,7 +48,7 @@ fn badArgs(comptime format: []const u8, args: ...) error {
     return error.InvalidCommandLineArguments;
 }
 
-pub fn main2() %void {
+pub fn main2() !void {
     const allocator = std.heap.c_allocator;
 
     const args = try os.argsAlloc(allocator);
@@ -472,7 +472,7 @@ pub fn main2() %void {
     }
 }
 
-fn printUsage(stream: &io.OutStream) %void {
+fn printUsage(stream: &io.OutStream) !void {
     try stream.write(
         \\Usage: zig [command] [options]
         \\
@@ -548,7 +548,7 @@ fn printUsage(stream: &io.OutStream) %void {
     );
 }
 
-fn printZen() %void {
+fn printZen() !void {
     var stdout_file = try io.getStdErr();
     try stdout_file.write(
         \\
@@ -569,7 +569,7 @@ fn printZen() %void {
 }
 
 /// Caller must free result
-fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) %[]u8 {
+fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) ![]u8 {
     if (zig_install_prefix_arg) |zig_install_prefix| {
         return testZigInstallPrefix(allocator, zig_install_prefix) catch |err| {
             warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err));
@@ -585,7 +585,7 @@ fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const
 }
 
 /// Caller must free result
-fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) %[]u8 {
+fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) ![]u8 {
     const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig");
     errdefer allocator.free(test_zig_dir);
 
@@ -599,7 +599,7 @@ fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) %[]u8
 }
 
 /// Caller must free result
-fn findZigLibDir(allocator: &mem.Allocator) %[]u8 {
+fn findZigLibDir(allocator: &mem.Allocator) ![]u8 {
     const self_exe_path = try os.selfExeDirPath(allocator);
     defer allocator.free(self_exe_path);
 
src-self-hosted/module.zig
@@ -198,7 +198,7 @@ pub const Module = struct {
         self.allocator.destroy(self);
     }
 
-    pub fn build(self: &Module) %void {
+    pub fn build(self: &Module) !void {
         if (self.llvm_argv.len != 0) {
             var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator,
                 [][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, });
@@ -263,11 +263,11 @@ pub const Module = struct {
         
     }
 
-    pub fn link(self: &Module, out_file: ?[]const u8) %void {
+    pub fn link(self: &Module, out_file: ?[]const u8) !void {
         warn("TODO link");
     }
 
-    pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) %&LinkLib {
+    pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) !&LinkLib {
         const is_libc = mem.eql(u8, name, "c");
 
         if (is_libc) {
@@ -297,7 +297,7 @@ pub const Module = struct {
     }
 };
 
-fn printError(comptime format: []const u8, args: ...) %void {
+fn printError(comptime format: []const u8, args: ...) !void {
     var stderr_file = try std.io.getStdErr();
     var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
     const out_stream = &stderr_file_out_stream.stream;
src-self-hosted/parser.zig
@@ -63,7 +63,7 @@ pub const Parser = struct {
         NullableField: &?&ast.Node,
         List: &ArrayList(&ast.Node),
 
-        pub fn store(self: &const DestPtr, value: &ast.Node) %void {
+        pub fn store(self: &const DestPtr, value: &ast.Node) !void {
             switch (*self) {
                 DestPtr.Field => |ptr| *ptr = value,
                 DestPtr.NullableField => |ptr| *ptr = value,
@@ -99,7 +99,7 @@ pub const Parser = struct {
 
     /// Returns an AST tree, allocated with the parser's allocator.
     /// Result should be freed with `freeAst` when done.
-    pub fn parse(self: &Parser) %Tree {
+    pub fn parse(self: &Parser) !Tree {
         var stack = self.initUtilityArrayList(State);
         defer self.deinitUtilityArrayList(stack);
 
@@ -544,7 +544,7 @@ pub const Parser = struct {
         }
     }
 
-    fn createRoot(self: &Parser) %&ast.NodeRoot {
+    fn createRoot(self: &Parser) !&ast.NodeRoot {
         const node = try self.allocator.create(ast.NodeRoot);
 
         *node = ast.NodeRoot {
@@ -599,7 +599,7 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createParamDecl(self: &Parser) %&ast.NodeParamDecl {
+    fn createParamDecl(self: &Parser) !&ast.NodeParamDecl {
         const node = try self.allocator.create(ast.NodeParamDecl);
 
         *node = ast.NodeParamDecl {
@@ -613,7 +613,7 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createBlock(self: &Parser, begin_token: &const Token) %&ast.NodeBlock {
+    fn createBlock(self: &Parser, begin_token: &const Token) !&ast.NodeBlock {
         const node = try self.allocator.create(ast.NodeBlock);
 
         *node = ast.NodeBlock {
@@ -625,7 +625,7 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) %&ast.NodeInfixOp {
+    fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) !&ast.NodeInfixOp {
         const node = try self.allocator.create(ast.NodeInfixOp);
 
         *node = ast.NodeInfixOp {
@@ -638,7 +638,7 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) %&ast.NodePrefixOp {
+    fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) !&ast.NodePrefixOp {
         const node = try self.allocator.create(ast.NodePrefixOp);
 
         *node = ast.NodePrefixOp {
@@ -650,7 +650,7 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createIdentifier(self: &Parser, name_token: &const Token) %&ast.NodeIdentifier {
+    fn createIdentifier(self: &Parser, name_token: &const Token) !&ast.NodeIdentifier {
         const node = try self.allocator.create(ast.NodeIdentifier);
 
         *node = ast.NodeIdentifier {
@@ -660,7 +660,7 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createIntegerLiteral(self: &Parser, token: &const Token) %&ast.NodeIntegerLiteral {
+    fn createIntegerLiteral(self: &Parser, token: &const Token) !&ast.NodeIntegerLiteral {
         const node = try self.allocator.create(ast.NodeIntegerLiteral);
 
         *node = ast.NodeIntegerLiteral {
@@ -670,7 +670,7 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createFloatLiteral(self: &Parser, token: &const Token) %&ast.NodeFloatLiteral {
+    fn createFloatLiteral(self: &Parser, token: &const Token) !&ast.NodeFloatLiteral {
         const node = try self.allocator.create(ast.NodeFloatLiteral);
 
         *node = ast.NodeFloatLiteral {
@@ -680,13 +680,13 @@ pub const Parser = struct {
         return node;
     }
 
-    fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) %&ast.NodeIdentifier {
+    fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) !&ast.NodeIdentifier {
         const node = try self.createIdentifier(name_token);
         try dest_ptr.store(&node.base);
         return node;
     }
 
-    fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) %&ast.NodeParamDecl {
+    fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) !&ast.NodeParamDecl {
         const node = try self.createParamDecl();
         try list.append(&node.base);
         return node;
@@ -730,13 +730,13 @@ pub const Parser = struct {
         return error.ParseError;
     }
 
-    fn expectToken(self: &Parser, token: &const Token, id: @TagType(Token.Id)) %void {
+    fn expectToken(self: &Parser, token: &const Token, id: @TagType(Token.Id)) !void {
         if (token.id != id) {
             return self.parseError(token, "expected {}, found {}", @tagName(id), @tagName(token.id));
         }
     }
 
-    fn eatToken(self: &Parser, id: @TagType(Token.Id)) %Token {
+    fn eatToken(self: &Parser, id: @TagType(Token.Id)) !Token {
         const token = self.getNextToken();
         try self.expectToken(token, id);
         return token;
@@ -763,7 +763,7 @@ pub const Parser = struct {
         indent: usize,
     };
 
-    pub fn renderAst(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) %void {
+    pub fn renderAst(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) !void {
         var stack = self.initUtilityArrayList(RenderAstFrame);
         defer self.deinitUtilityArrayList(stack);
 
@@ -802,7 +802,7 @@ pub const Parser = struct {
         Indent: usize,
     };
 
-    pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) %void {
+    pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) !void {
         var stack = self.initUtilityArrayList(RenderState);
         defer self.deinitUtilityArrayList(stack);
 
@@ -1038,7 +1038,7 @@ pub const Parser = struct {
 
 var fixed_buffer_mem: [100 * 1024]u8 = undefined;
 
-fn testParse(source: []const u8, allocator: &mem.Allocator) %[]u8 {
+fn testParse(source: []const u8, allocator: &mem.Allocator) ![]u8 {
     var padded_source: [0x100]u8 = undefined;
     std.mem.copy(u8, padded_source[0..source.len], source);
     padded_source[source.len + 0] = '\n';
@@ -1064,7 +1064,7 @@ error MemoryLeakDetected;
 
 // TODO test for memory leaks
 // TODO test for valid frees
-fn testCanonical(source: []const u8) %void {
+fn testCanonical(source: []const u8) !void {
     const needed_alloc_count = x: {
         // Try it once with unlimited memory, make sure it works
         var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
std/crypto/throughput_test.zig
@@ -18,7 +18,7 @@ const c = @cImport({
 
 const Mb = 1024 * 1024;
 
-pub fn main() %void {
+pub fn main() !void {
     var stdout_file = try std.io.getStdOut();
     var stdout_out_stream = std.io.FileOutStream.init(&stdout_file);
     const stdout = &stdout_out_stream.stream;
std/debug/failing_allocator.zig
@@ -28,7 +28,7 @@ pub const FailingAllocator = struct {
         };
     }
 
-    fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) %[]u8 {
+    fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) ![]u8 {
         const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
         if (self.index == self.fail_index) {
             return error.OutOfMemory;
@@ -39,7 +39,7 @@ pub const FailingAllocator = struct {
         return result;
     }
 
-    fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
+    fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
         const self = @fieldParentPtr(FailingAllocator, "allocator", allocator);
         if (new_size <= old_mem.len) {
             self.freed_bytes += old_mem.len - new_size;
std/fmt/index.zig
@@ -24,8 +24,8 @@ const State = enum { // TODO put inside format function and make sure the name a
 /// Renders fmt string with args, calling output with slices of bytes.
 /// If `output` returns an error, the error is returned from `format` and
 /// `output` is not called again.
-pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
-    comptime fmt: []const u8, args: ...) %void
+pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void,
+    comptime fmt: []const u8, args: ...) Errors!void
 {
     comptime var start_index = 0;
     comptime var state = State.Start;
@@ -58,7 +58,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
                     start_index = i;
                 },
                 '}' => {
-                    try formatValue(args[next_arg], context, output);
+                    try formatValue(args[next_arg], context, Errors, output);
                     next_arg += 1;
                     state = State.Start;
                     start_index = i + 1;
@@ -110,7 +110,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
             },
             State.Integer => switch (c) {
                 '}' => {
-                    try formatInt(args[next_arg], radix, uppercase, width, context, output);
+                    try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);
                     next_arg += 1;
                     state = State.Start;
                     start_index = i + 1;
@@ -124,7 +124,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
             State.IntegerWidth => switch (c) {
                 '}' => {
                     width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
-                    try formatInt(args[next_arg], radix, uppercase, width, context, output);
+                    try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);
                     next_arg += 1;
                     state = State.Start;
                     start_index = i + 1;
@@ -134,7 +134,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
             },
             State.Float => switch (c) {
                 '}' => {
-                    try formatFloatDecimal(args[next_arg], 0, context, output);
+                    try formatFloatDecimal(args[next_arg], 0, context, Errors, output);
                     next_arg += 1;
                     state = State.Start;
                     start_index = i + 1;
@@ -148,7 +148,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
             State.FloatWidth => switch (c) {
                 '}' => {
                     width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
-                    try formatFloatDecimal(args[next_arg], width, context, output);
+                    try formatFloatDecimal(args[next_arg], width, context, Errors, output);
                     next_arg += 1;
                     state = State.Start;
                     start_index = i + 1;
@@ -159,7 +159,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
             State.BufWidth => switch (c) {
                 '}' => {
                     width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
-                    try formatBuf(args[next_arg], width, context, output);
+                    try formatBuf(args[next_arg], width, context, Errors, output);
                     next_arg += 1;
                     state = State.Start;
                     start_index = i + 1;
@@ -169,7 +169,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
             },
             State.Character => switch (c) {
                 '}' => {
-                    try formatAsciiChar(args[next_arg], context, output);
+                    try formatAsciiChar(args[next_arg], context, Errors, output);
                     next_arg += 1;
                     state = State.Start;
                     start_index = i + 1;
@@ -191,7 +191,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void,
     }
 }
 
-pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
+pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
     const T = @typeOf(value);
     switch (@typeId(T)) {
         builtin.TypeId.Int => {
@@ -208,16 +208,16 @@ pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []cons
         },
         builtin.TypeId.Nullable => {
             if (value) |payload| {
-                return formatValue(payload, context, output);
+                return formatValue(payload, context, Errors, output);
             } else {
                 return output(context, "null");
             }
         },
         builtin.TypeId.ErrorUnion => {
             if (value) |payload| {
-                return formatValue(payload, context, output);
+                return formatValue(payload, context, Errors, output);
             } else |err| {
-                return formatValue(err, context, output);
+                return formatValue(err, context, Errors, output);
             }
         },
         builtin.TypeId.Error => {
@@ -240,12 +240,12 @@ pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []cons
     }
 }
 
-pub fn formatAsciiChar(c: u8, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
+pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
     return output(context, (&c)[0..1]);
 }
 
 pub fn formatBuf(buf: []const u8, width: usize,
-    context: var, output: fn(@typeOf(context), []const u8)%void) %void
+    context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
 {
     try output(context, buf);
 
@@ -256,7 +256,7 @@ pub fn formatBuf(buf: []const u8, width: usize,
     }
 }
 
-pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
+pub fn formatFloat(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
     var x = f64(value);
 
     // Errol doesn't handle these special cases.
@@ -294,7 +294,7 @@ pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []cons
     }
 }
 
-pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn(@typeOf(context), []const u8)%void) %void {
+pub fn formatFloatDecimal(value: var, precision: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
     var x = f64(value);
 
     // Errol doesn't handle these special cases.
@@ -336,7 +336,7 @@ pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn
 
 
 pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
-    context: var, output: fn(@typeOf(context), []const u8)%void) %void
+    context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)errors!void) errors!void
 {
     if (@typeOf(value).is_signed) {
         return formatIntSigned(value, base, uppercase, width, context, output);
@@ -346,7 +346,7 @@ pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
 }
 
 fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
-    context: var, output: fn(@typeOf(context), []const u8)%void) %void
+    context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
 {
     const uint = @IntType(false, @typeOf(value).bit_count);
     if (value < 0) {
@@ -367,7 +367,7 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
 }
 
 fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
-    context: var, output: fn(@typeOf(context), []const u8)%void) %void
+    context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
 {
     // max_int_digits accounts for the minus sign. when printing an unsigned
     // number we don't need to do that.
@@ -417,12 +417,12 @@ const FormatIntBuf = struct {
     out_buf: []u8,
     index: usize,
 };
-fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) %void {
+fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) !void {
     mem.copy(u8, context.out_buf[context.index..], bytes);
     context.index += bytes.len;
 }
 
-pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) %T {
+pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
     if (!T.is_signed)
         return parseUnsigned(T, buf, radix);
     if (buf.len == 0)
@@ -446,7 +446,7 @@ test "fmt.parseInt" {
     assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
 }
 
-pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) %T {
+pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) !T {
     var x: T = 0;
 
     for (buf) |c| {
@@ -458,8 +458,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) %T {
     return x;
 }
 
-error InvalidChar;
-fn charToDigit(c: u8, radix: u8) %u8 {
+fn charToDigit(c: u8, radix: u8) !u8 {
     const value = switch (c) {
         '0' ... '9' => c - '0',
         'A' ... 'Z' => c - 'A' + 10,
@@ -485,28 +484,26 @@ const BufPrintContext = struct {
     remaining: []u8,
 };
 
-error BufferTooSmall;
-fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) %void {
+fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void {
     if (context.remaining.len < bytes.len) return error.BufferTooSmall;
     mem.copy(u8, context.remaining, bytes);
     context.remaining = context.remaining[bytes.len..];
 }
 
-pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) %[]u8 {
+pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 {
     var context = BufPrintContext { .remaining = buf, };
     try format(&context, bufPrintWrite, fmt, args);
     return buf[0..buf.len - context.remaining.len];
 }
 
-pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) %[]u8 {
+pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) ![]u8 {
     var size: usize = 0;
-    // Cannot fail because `countSize` cannot fail.
-    format(&size, countSize, fmt, args) catch unreachable;
+    format(&size, error{}, countSize, fmt, args);
     const buf = try allocator.alloc(u8, size);
     return bufPrint(buf, fmt, args);
 }
 
-fn countSize(size: &usize, bytes: []const u8) %void {
+fn countSize(size: &usize, bytes: []const u8) void {
     *size += bytes.len;
 }
 
@@ -561,13 +558,13 @@ test "fmt.format" {
     }
     {
         var buf1: [32]u8 = undefined;
-        const value: %i32 = 1234;
+        const value: error!i32 = 1234;
         const result = try bufPrint(buf1[0..], "error union: {}\n", value);
         assert(mem.eql(u8, result, "error union: 1234\n"));
     }
     {
         var buf1: [32]u8 = undefined;
-        const value: %i32 = error.InvalidChar;
+        const value: error!i32 = error.InvalidChar;
         const result = try bufPrint(buf1[0..], "error union: {}\n", value);
         assert(mem.eql(u8, result, "error union: error.InvalidChar\n"));
     }
std/math/index.zig
@@ -191,30 +191,26 @@ test "math.max" {
     assert(max(i32(-1), i32(2)) == 2);
 }
 
-error Overflow;
-pub fn mul(comptime T: type, a: T, b: T) %T {
+pub fn mul(comptime T: type, a: T, b: T) !T {
     var answer: T = undefined;
     return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer;
 }
 
-error Overflow;
-pub fn add(comptime T: type, a: T, b: T) %T {
+pub fn add(comptime T: type, a: T, b: T) !T {
     var answer: T = undefined;
     return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
 }
 
-error Overflow;
-pub fn sub(comptime T: type, a: T, b: T) %T {
+pub fn sub(comptime T: type, a: T, b: T) !T {
     var answer: T = undefined;
     return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer;
 }
 
-pub fn negate(x: var) %@typeOf(x) {
+pub fn negate(x: var) !@typeOf(x) {
     return sub(@typeOf(x), 0, x);
 }
 
-error Overflow;
-pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) %T {
+pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {
     var answer: T = undefined;
     return if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer;
 }
@@ -323,8 +319,7 @@ fn testOverflow() void {
 }
 
 
-error Overflow;
-pub fn absInt(x: var) %@typeOf(x) {
+pub fn absInt(x: var) !@typeOf(x) {
     const T = @typeOf(x);
     comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
     comptime assert(T.is_signed); // must pass a signed integer to absInt
@@ -347,9 +342,7 @@ fn testAbsInt() void {
 
 pub const absFloat = @import("fabs.zig").fabs;
 
-error DivisionByZero;
-error Overflow;
-pub fn divTrunc(comptime T: type, numerator: T, denominator: T) %T {
+pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
     @setRuntimeSafety(false);
     if (denominator == 0)
         return error.DivisionByZero;
@@ -372,9 +365,7 @@ fn testDivTrunc() void {
     assert((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0);
 }
 
-error DivisionByZero;
-error Overflow;
-pub fn divFloor(comptime T: type, numerator: T, denominator: T) %T {
+pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
     @setRuntimeSafety(false);
     if (denominator == 0)
         return error.DivisionByZero;
@@ -397,10 +388,7 @@ fn testDivFloor() void {
     assert((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0);
 }
 
-error DivisionByZero;
-error Overflow;
-error UnexpectedRemainder;
-pub fn divExact(comptime T: type, numerator: T, denominator: T) %T {
+pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
     @setRuntimeSafety(false);
     if (denominator == 0)
         return error.DivisionByZero;
@@ -428,9 +416,7 @@ fn testDivExact() void {
     if (divExact(f32, 5.0, 2.0)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder);
 }
 
-error DivisionByZero;
-error NegativeDenominator;
-pub fn mod(comptime T: type, numerator: T, denominator: T) %T {
+pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
     @setRuntimeSafety(false);
     if (denominator == 0)
         return error.DivisionByZero;
@@ -455,9 +441,7 @@ fn testMod() void {
     if (mod(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
 }
 
-error DivisionByZero;
-error NegativeDenominator;
-pub fn rem(comptime T: type, numerator: T, denominator: T) %T {
+pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
     @setRuntimeSafety(false);
     if (denominator == 0)
         return error.DivisionByZero;
@@ -505,8 +489,7 @@ test "math.absCast" {
 
 /// Returns the negation of the integer parameter.
 /// Result is a signed integer.
-error Overflow;
-pub fn negateCast(x: var) %@IntType(true, @typeOf(x).bit_count) {
+pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {
     if (@typeOf(x).is_signed)
         return negate(x);
 
@@ -532,8 +515,7 @@ test "math.negateCast" {
 
 /// Cast an integer to a different integer type. If the value doesn't fit, 
 /// return an error.
-error Overflow;
-pub fn cast(comptime T: type, x: var) %T {
+pub fn cast(comptime T: type, x: var) !T {
     comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer
     if (x > @maxValue(T)) {
         return error.Overflow;
std/os/windows/util.zig
@@ -6,11 +6,7 @@ const mem = std.mem;
 const BufMap = std.BufMap;
 const cstr = std.cstr;
 
-error WaitAbandoned;
-error WaitTimeOut;
-error Unexpected;
-
-pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) %void {
+pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) !void {
     const result = windows.WaitForSingleObject(handle, milliseconds);
     return switch (result) {
         windows.WAIT_ABANDONED => error.WaitAbandoned,
@@ -30,12 +26,7 @@ pub fn windowsClose(handle: windows.HANDLE) void {
     assert(windows.CloseHandle(handle) != 0);
 }
 
-error SystemResources;
-error OperationAborted;
-error IoPending;
-error BrokenPipe;
-
-pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) %void {
+pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) !void {
     if (windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) {
         const err = windows.GetLastError();
         return switch (err) {
@@ -75,9 +66,6 @@ pub fn windowsIsCygwinPty(handle: windows.HANDLE) bool {
            mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null;
 }
 
-error SharingViolation;
-error PipeBusy;
-
 /// `file_path` may need to be copied in memory to add a null terminating byte. In this case
 /// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed
 /// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned.
@@ -120,7 +108,7 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m
 }
 
 /// Caller must free result.
-pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) %[]u8 {
+pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) ![]u8 {
     // count bytes needed
     const bytes_needed = x: {
         var bytes_needed: usize = 1; // 1 for the final null byte
@@ -151,8 +139,7 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap)
     return result;
 }
 
-error DllNotFound;
-pub fn windowsLoadDll(allocator: &mem.Allocator, dll_path: []const u8) %windows.HMODULE {
+pub fn windowsLoadDll(allocator: &mem.Allocator, dll_path: []const u8) !windows.HMODULE {
     const padded_buff = try cstr.addNullByte(allocator, dll_path);
     defer allocator.free(padded_buff);
     return windows.LoadLibraryA(padded_buff.ptr) ?? error.DllNotFound;
std/os/child_process.zig
@@ -13,10 +13,6 @@ const builtin = @import("builtin");
 const Os = builtin.Os;
 const LinkedList = std.LinkedList;
 
-error PermissionDenied;
-error ProcessNotFound;
-error InvalidName;
-
 var children_nodes = LinkedList(&ChildProcess).init();
 
 const is_windows = builtin.os == Os.windows;
@@ -74,7 +70,7 @@ pub const ChildProcess = struct {
 
     /// First argument in argv is the executable.
     /// On success must call deinit.
-    pub fn init(argv: []const []const u8, allocator: &mem.Allocator) %&ChildProcess {
+    pub fn init(argv: []const []const u8, allocator: &mem.Allocator) !&ChildProcess {
         const child = try allocator.create(ChildProcess);
         errdefer allocator.destroy(child);
 
@@ -103,7 +99,7 @@ pub const ChildProcess = struct {
         return child;
     }
 
-    pub fn setUserName(self: &ChildProcess, name: []const u8) %void {
+    pub fn setUserName(self: &ChildProcess, name: []const u8) !void {
         const user_info = try os.getUserInfo(name);
         self.uid = user_info.uid;
         self.gid = user_info.gid;
@@ -111,7 +107,7 @@ pub const ChildProcess = struct {
 
     /// onTerm can be called before `spawn` returns.
     /// On success must call `kill` or `wait`.
-    pub fn spawn(self: &ChildProcess) %void {
+    pub fn spawn(self: &ChildProcess) !void {
         if (is_windows) {
             return self.spawnWindows();
         } else {
@@ -119,13 +115,13 @@ pub const ChildProcess = struct {
         }
     }
 
-    pub fn spawnAndWait(self: &ChildProcess) %Term {
+    pub fn spawnAndWait(self: &ChildProcess) !Term {
         try self.spawn();
         return self.wait();
     }
 
     /// Forcibly terminates child process and then cleans up all resources.
-    pub fn kill(self: &ChildProcess) %Term {
+    pub fn kill(self: &ChildProcess) !Term {
         if (is_windows) {
             return self.killWindows(1);
         } else {
@@ -133,7 +129,7 @@ pub const ChildProcess = struct {
         }
     }
 
-    pub fn killWindows(self: &ChildProcess, exit_code: windows.UINT) %Term {
+    pub fn killWindows(self: &ChildProcess, exit_code: windows.UINT) !Term {
         if (self.term) |term| {
             self.cleanupStreams();
             return term;
@@ -149,7 +145,7 @@ pub const ChildProcess = struct {
         return ??self.term;
     }
 
-    pub fn killPosix(self: &ChildProcess) %Term {
+    pub fn killPosix(self: &ChildProcess) !Term {
         block_SIGCHLD();
         defer restore_SIGCHLD();
 
@@ -172,7 +168,7 @@ pub const ChildProcess = struct {
     }
 
     /// Blocks until child process terminates and then cleans up all resources.
-    pub fn wait(self: &ChildProcess) %Term {
+    pub fn wait(self: &ChildProcess) !Term {
         if (is_windows) {
             return self.waitWindows();
         } else {
@@ -220,7 +216,7 @@ pub const ChildProcess = struct {
         };
     }
 
-    fn waitWindows(self: &ChildProcess) %Term {
+    fn waitWindows(self: &ChildProcess) !Term {
         if (self.term) |term| {
             self.cleanupStreams();
             return term;
@@ -230,7 +226,7 @@ pub const ChildProcess = struct {
         return ??self.term;
     }
 
-    fn waitPosix(self: &ChildProcess) %Term {
+    fn waitPosix(self: &ChildProcess) !Term {
         block_SIGCHLD();
         defer restore_SIGCHLD();
 
@@ -247,7 +243,7 @@ pub const ChildProcess = struct {
         self.allocator.destroy(self);
     }
 
-    fn waitUnwrappedWindows(self: &ChildProcess) %void {
+    fn waitUnwrappedWindows(self: &ChildProcess) !void {
         const result = os.windowsWaitSingle(self.handle, windows.INFINITE);
 
         self.term = (%Term)(x: {
@@ -295,7 +291,7 @@ pub const ChildProcess = struct {
         if (self.stderr) |*stderr| { stderr.close(); self.stderr = null; }
     }
 
-    fn cleanupAfterWait(self: &ChildProcess, status: i32) %Term {
+    fn cleanupAfterWait(self: &ChildProcess, status: i32) !Term {
         children_nodes.remove(&self.llnode);
 
         defer {
@@ -331,7 +327,7 @@ pub const ChildProcess = struct {
         ;
     }
 
-    fn spawnPosix(self: &ChildProcess) %void {
+    fn spawnPosix(self: &ChildProcess) !void {
         // TODO atomically set a flag saying that we already did this
         install_SIGCHLD_handler();
 
@@ -440,7 +436,7 @@ pub const ChildProcess = struct {
         if (self.stderr_behavior == StdIo.Pipe) { os.close(stderr_pipe[1]); }
     }
 
-    fn spawnWindows(self: &ChildProcess) %void {
+    fn spawnWindows(self: &ChildProcess) !void {
         const saAttr = windows.SECURITY_ATTRIBUTES {
             .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),
             .bInheritHandle = windows.TRUE,
@@ -623,7 +619,7 @@ pub const ChildProcess = struct {
         if (self.stdout_behavior == StdIo.Pipe) { os.close(??g_hChildStd_OUT_Wr); }
     }
 
-    fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) %void {
+    fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void {
         switch (stdio) {
             StdIo.Pipe => try os.posixDup2(pipe_fd, std_fileno),
             StdIo.Close => os.close(std_fileno),
@@ -655,7 +651,7 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?
 
 /// Caller must dealloc.
 /// Guarantees a null byte at result[result.len].
-fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) %[]u8 {
+fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) ![]u8 {
     var buf = try Buffer.initSize(allocator, 0);
     defer buf.deinit();
 
@@ -700,7 +696,7 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void {
 // a namespace field lookup
 const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES;
 
-fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) %void {
+fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void {
     if (windows.CreatePipe(rd, wr, sattr, 0) == 0) {
         const err = windows.GetLastError();
         return switch (err) {
@@ -709,7 +705,7 @@ fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECUR
     }
 }
 
-fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.DWORD) %void {
+fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.DWORD) !void {
     if (windows.SetHandleInformation(h, mask, flags) == 0) {
         const err = windows.GetLastError();
         return switch (err) {
@@ -718,7 +714,7 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D
     }
 }
 
-fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) %void {
+fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void {
     var rd_h: windows.HANDLE = undefined;
     var wr_h: windows.HANDLE = undefined;
     try windowsMakePipe(&rd_h, &wr_h, sattr);
@@ -728,7 +724,7 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S
     *wr = wr_h;
 }
 
-fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) %void {
+fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void {
     var rd_h: windows.HANDLE = undefined;
     var wr_h: windows.HANDLE = undefined;
     try windowsMakePipe(&rd_h, &wr_h, sattr);
@@ -738,7 +734,7 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const
     *wr = wr_h;
 }
 
-fn makePipe() %[2]i32 {
+fn makePipe() ![2]i32 {
     var fds: [2]i32 = undefined;
     const err = posix.getErrno(posix.pipe(&fds));
     if (err > 0) {
@@ -764,13 +760,13 @@ fn forkChildErrReport(fd: i32, err: error) noreturn {
 
 const ErrInt = @IntType(false, @sizeOf(error) * 8);
 
-fn writeIntFd(fd: i32, value: ErrInt) %void {
+fn writeIntFd(fd: i32, value: ErrInt) !void {
     var bytes: [@sizeOf(ErrInt)]u8 = undefined;
     mem.writeInt(bytes[0..], value, builtin.endian);
     os.posixWrite(fd, bytes[0..]) catch return error.SystemResources;
 }
 
-fn readIntFd(fd: i32) %ErrInt {
+fn readIntFd(fd: i32) !ErrInt {
     var bytes: [@sizeOf(ErrInt)]u8 = undefined;
     os.posixRead(fd, bytes[0..]) catch return error.SystemResources;
     return mem.readInt(bytes[0..], ErrInt, builtin.endian);
std/os/get_user_id.zig
@@ -9,7 +9,7 @@ pub const UserInfo = struct {
 };
 
 /// POSIX function which gets a uid from username.
-pub fn getUserInfo(name: []const u8) %UserInfo {
+pub fn getUserInfo(name: []const u8) !UserInfo {
     return switch (builtin.os) {
         Os.linux, Os.macosx, Os.ios => posixGetUserInfo(name),
         else => @compileError("Unsupported OS"),
@@ -24,13 +24,10 @@ const State = enum {
     ReadGroupId,
 };
 
-error UserNotFound;
-error CorruptPasswordFile;
-
 // TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else
 // like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`.
 
-pub fn posixGetUserInfo(name: []const u8) %UserInfo {
+pub fn posixGetUserInfo(name: []const u8) !UserInfo {
     var in_stream = try io.InStream.open("/etc/passwd", null);
     defer in_stream.close();
 
std/os/index.zig
@@ -1470,8 +1470,6 @@ test "std.os" {
 }
 
 
-error Unexpected;
-
 // TODO make this a build variable that you can set
 const unexpected_error_tracing = false;
 
std/os/linux.zig
@@ -720,7 +720,7 @@ pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags:
 // error SystemResources;
 // error Io;
 // 
-// pub fn if_nametoindex(name: []u8) %u32 {
+// pub fn if_nametoindex(name: []u8) !u32 {
 //     var ifr: ifreq = undefined;
 // 
 //     if (name.len >= ifr.ifr_name.len) {
std/os/path.zig
@@ -32,7 +32,7 @@ pub fn isSep(byte: u8) bool {
 
 /// Naively combines a series of paths with the native path seperator.
 /// Allocates memory for the result, which must be freed by the caller.
-pub fn join(allocator: &Allocator, paths: ...) %[]u8 {
+pub fn join(allocator: &Allocator, paths: ...) ![]u8 {
     if (is_windows) {
         return joinWindows(allocator, paths);
     } else {
@@ -40,11 +40,11 @@ pub fn join(allocator: &Allocator, paths: ...) %[]u8 {
     }
 }
 
-pub fn joinWindows(allocator: &Allocator, paths: ...) %[]u8 {
+pub fn joinWindows(allocator: &Allocator, paths: ...) ![]u8 {
     return mem.join(allocator, sep_windows, paths);
 }
 
-pub fn joinPosix(allocator: &Allocator, paths: ...) %[]u8 {
+pub fn joinPosix(allocator: &Allocator, paths: ...) ![]u8 {
     return mem.join(allocator, sep_posix, paths);
 }
 
@@ -313,7 +313,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
 }
 
 /// Converts the command line arguments into a slice and calls `resolveSlice`.
-pub fn resolve(allocator: &Allocator, args: ...) %[]u8 {
+pub fn resolve(allocator: &Allocator, args: ...) ![]u8 {
     var paths: [args.len][]const u8 = undefined;
     comptime var arg_i = 0;
     inline while (arg_i < args.len) : (arg_i += 1) {
@@ -323,7 +323,7 @@ pub fn resolve(allocator: &Allocator, args: ...) %[]u8 {
 }
 
 /// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
-pub fn resolveSlice(allocator: &Allocator, paths: []const []const u8) %[]u8 {
+pub fn resolveSlice(allocator: &Allocator, paths: []const []const u8) ![]u8 {
     if (is_windows) {
         return resolveWindows(allocator, paths);
     } else {
@@ -337,7 +337,7 @@ pub fn resolveSlice(allocator: &Allocator, paths: []const []const u8) %[]u8 {
 /// If all paths are relative it uses the current working directory as a starting point.
 /// Each drive has its own current working directory.
 /// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters.
-pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) %[]u8 {
+pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) ![]u8 {
     if (paths.len == 0) {
         assert(is_windows); // resolveWindows called on non windows can't use getCwd
         return os.getCwd(allocator);
@@ -520,7 +520,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) %[]u8 {
 /// It resolves "." and "..".
 /// The result does not have a trailing path separator.
 /// If all paths are relative it uses the current working directory as a starting point.
-pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) %[]u8 {
+pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) ![]u8 {
     if (paths.len == 0) {
         assert(!is_windows); // resolvePosix called on windows can't use getCwd
         return os.getCwd(allocator);
@@ -890,7 +890,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {
 /// resolve to the same path (after calling `resolve` on each), a zero-length
 /// string is returned.
 /// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.
-pub fn relative(allocator: &Allocator, from: []const u8, to: []const u8) %[]u8 {
+pub fn relative(allocator: &Allocator, from: []const u8, to: []const u8) ![]u8 {
     if (is_windows) {
         return relativeWindows(allocator, from, to);
     } else {
@@ -898,7 +898,7 @@ pub fn relative(allocator: &Allocator, from: []const u8, to: []const u8) %[]u8 {
     }
 }
 
-pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8) %[]u8 {
+pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8) ![]u8 {
     const resolved_from = try resolveWindows(allocator, [][]const u8{from});
     defer allocator.free(resolved_from);
 
@@ -971,7 +971,7 @@ pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8)
     return []u8{};
 }
 
-pub fn relativePosix(allocator: &Allocator, from: []const u8, to: []const u8) %[]u8 {
+pub fn relativePosix(allocator: &Allocator, from: []const u8, to: []const u8) ![]u8 {
     const resolved_from = try resolvePosix(allocator, [][]const u8{from});
     defer allocator.free(resolved_from);
 
@@ -1066,18 +1066,11 @@ fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []cons
     assert(mem.eql(u8, result, expected_output));
 }
 
-error AccessDenied;
-error FileNotFound;
-error NotSupported;
-error NotDir;
-error NameTooLong;
-error SymLinkLoop;
-error InputOutput;
 /// Return the canonicalized absolute pathname.
 /// Expands all symbolic links and resolves references to `.`, `..`, and
 /// extra `/` characters in ::pathname.
 /// Caller must deallocate result.
-pub fn real(allocator: &Allocator, pathname: []const u8) %[]u8 {
+pub fn real(allocator: &Allocator, pathname: []const u8) ![]u8 {
     switch (builtin.os) {
         Os.windows => {
             const pathname_buf = try allocator.alloc(u8, pathname.len + 1);
std/special/build_file_template.zig
@@ -1,6 +1,6 @@
 const Builder = @import("std").build.Builder;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     const mode = b.standardReleaseOptions();
     const exe = b.addExecutable("YOUR_NAME_HERE", "src/main.zig");
     exe.setBuildMode(mode);
std/special/build_runner.zig
@@ -8,9 +8,7 @@ const mem = std.mem;
 const ArrayList = std.ArrayList;
 const warn = std.debug.warn;
 
-error InvalidArgs;
-
-pub fn main() %void {
+pub fn main() !void {
     var arg_it = os.args();
 
     // TODO use a more general purpose allocator here
@@ -125,7 +123,7 @@ pub fn main() %void {
     };
 }
 
-fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) %void {
+fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) !void {
     // run the build script to collect the options
     if (!already_ran_build) {
         builder.setInstallPrefix(null);
@@ -188,7 +186,7 @@ fn usageAndErr(builder: &Builder, already_ran_build: bool, out_stream: &io.OutSt
     return error.InvalidArgs;
 }
 
-fn unwrapArg(arg: %[]u8) %[]u8 {
+fn unwrapArg(arg: %[]u8) ![]u8 {
     return arg catch |err| {
         warn("Unable to parse command line: {}\n", err);
         return err;
std/array_list.zig
@@ -59,18 +59,18 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
             return result;
         }
 
-        pub fn append(l: &Self, item: &const T) %void {
+        pub fn append(l: &Self, item: &const T) !void {
             const new_item_ptr = try l.addOne();
             *new_item_ptr = *item;
         }
 
-        pub fn appendSlice(l: &Self, items: []align(A) const T) %void {
+        pub fn appendSlice(l: &Self, items: []align(A) const T) !void {
             try l.ensureCapacity(l.len + items.len);
             mem.copy(T, l.items[l.len..], items);
             l.len += items.len;
         }
 
-        pub fn resize(l: &Self, new_len: usize) %void {
+        pub fn resize(l: &Self, new_len: usize) !void {
             try l.ensureCapacity(new_len);
             l.len = new_len;
         }
@@ -80,7 +80,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
             l.len = new_len;
         }
 
-        pub fn ensureCapacity(l: &Self, new_capacity: usize) %void {
+        pub fn ensureCapacity(l: &Self, new_capacity: usize) !void {
             var better_capacity = l.items.len;
             if (better_capacity >= new_capacity) return;
             while (true) {
@@ -90,7 +90,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
             l.items = try l.allocator.alignedRealloc(T, A, l.items, better_capacity);
         }
 
-        pub fn addOne(l: &Self) %&T {
+        pub fn addOne(l: &Self) !&T {
             const new_length = l.len + 1;
             try l.ensureCapacity(new_length);
             const result = &l.items[l.len];
std/base64.zig
@@ -79,8 +79,6 @@ pub const Base64Encoder = struct {
 };
 
 pub const standard_decoder = Base64Decoder.init(standard_alphabet_chars, standard_pad_char);
-error InvalidPadding;
-error InvalidCharacter;
 
 pub const Base64Decoder = struct {
     /// e.g. 'A' => 0.
@@ -111,7 +109,7 @@ pub const Base64Decoder = struct {
     }
 
     /// If the encoded buffer is detected to be invalid, returns error.InvalidPadding.
-    pub fn calcSize(decoder: &const Base64Decoder, source: []const u8) %usize {
+    pub fn calcSize(decoder: &const Base64Decoder, source: []const u8) !usize {
         if (source.len % 4 != 0) return error.InvalidPadding;
         return calcDecodedSizeExactUnsafe(source, decoder.pad_char);
     }
@@ -119,7 +117,7 @@ pub const Base64Decoder = struct {
     /// dest.len must be what you get from ::calcSize.
     /// invalid characters result in error.InvalidCharacter.
     /// invalid padding results in error.InvalidPadding.
-    pub fn decode(decoder: &const Base64Decoder, dest: []u8, source: []const u8) %void {
+    pub fn decode(decoder: &const Base64Decoder, dest: []u8, source: []const u8) !void {
         assert(dest.len == (decoder.calcSize(source) catch unreachable));
         assert(source.len % 4 == 0);
 
@@ -163,8 +161,6 @@ pub const Base64Decoder = struct {
     }
 };
 
-error OutputTooSmall;
-
 pub const Base64DecoderWithIgnore = struct {
     decoder: Base64Decoder,
     char_is_ignored: [256]bool,
@@ -185,7 +181,7 @@ pub const Base64DecoderWithIgnore = struct {
     }
 
     /// If no characters end up being ignored or padding, this will be the exact decoded size.
-    pub fn calcSizeUpperBound(encoded_len: usize) %usize {
+    pub fn calcSizeUpperBound(encoded_len: usize) !usize {
         return @divTrunc(encoded_len, 4) * 3;
     }
 
@@ -193,7 +189,7 @@ pub const Base64DecoderWithIgnore = struct {
     /// Invalid padding results in error.InvalidPadding.
     /// Decoding more data than can fit in dest results in error.OutputTooSmall. See also ::calcSizeUpperBound.
     /// Returns the number of bytes writen to dest.
-    pub fn decode(decoder_with_ignore: &const Base64DecoderWithIgnore, dest: []u8, source: []const u8) %usize {
+    pub fn decode(decoder_with_ignore: &const Base64DecoderWithIgnore, dest: []u8, source: []const u8) !usize {
         const decoder = &decoder_with_ignore.decoder;
 
         var src_cursor: usize = 0;
@@ -378,7 +374,7 @@ test "base64" {
     comptime (testBase64() catch unreachable);
 }
 
-fn testBase64() %void {
+fn testBase64() !void {
     try testAllApis("",       "");
     try testAllApis("f",      "Zg==");
     try testAllApis("fo",     "Zm8=");
@@ -412,7 +408,7 @@ fn testBase64() %void {
     try testOutputTooSmallError("AAAAAA==");
 }
 
-fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) %void {
+fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void {
     // Base64Encoder
     {
         var buffer: [0x100]u8 = undefined;
@@ -449,7 +445,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) %void
     }
 }
 
-fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) %void {
+fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !void {
     const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
         standard_alphabet_chars, standard_pad_char, " ");
     var buffer: [0x100]u8 = undefined;
@@ -458,8 +454,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) %voi
     assert(mem.eql(u8, decoded[0..written], expected_decoded));
 }
 
-error ExpectedError;
-fn testError(encoded: []const u8, expected_err: error) %void {
+fn testError(encoded: []const u8, expected_err: error) !void {
     const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
         standard_alphabet_chars, standard_pad_char, " ");
     var buffer: [0x100]u8 = undefined;
@@ -475,7 +470,7 @@ fn testError(encoded: []const u8, expected_err: error) %void {
     } else |err| if (err != expected_err) return err;
 }
 
-fn testOutputTooSmallError(encoded: []const u8) %void {
+fn testOutputTooSmallError(encoded: []const u8) !void {
     const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
         standard_alphabet_chars, standard_pad_char, " ");
     var buffer: [0x100]u8 = undefined;
std/buf_map.zig
@@ -27,7 +27,7 @@ pub const BufMap = struct {
         self.hash_map.deinit();
     }
 
-    pub fn set(self: &BufMap, key: []const u8, value: []const u8) %void {
+    pub fn set(self: &BufMap, key: []const u8, value: []const u8) !void {
         if (self.hash_map.get(key)) |entry| {
             const value_copy = try self.copy(value);
             errdefer self.free(value_copy);
@@ -67,7 +67,7 @@ pub const BufMap = struct {
         self.hash_map.allocator.free(mut_value);
     }
 
-    fn copy(self: &BufMap, value: []const u8) %[]const u8 {
+    fn copy(self: &BufMap, value: []const u8) ![]const u8 {
         const result = try self.hash_map.allocator.alloc(u8, value.len);
         mem.copy(u8, result, value);
         return result;
std/buf_set.zig
@@ -24,7 +24,7 @@ pub const BufSet = struct {
         self.hash_map.deinit();
     }
 
-    pub fn put(self: &BufSet, key: []const u8) %void {
+    pub fn put(self: &BufSet, key: []const u8) !void {
         if (self.hash_map.get(key) == null) {
             const key_copy = try self.copy(key);
             errdefer self.free(key_copy);
@@ -55,7 +55,7 @@ pub const BufSet = struct {
         self.hash_map.allocator.free(mut_value);
     }
 
-    fn copy(self: &BufSet, value: []const u8) %[]const u8 {
+    fn copy(self: &BufSet, value: []const u8) ![]const u8 {
         const result = try self.hash_map.allocator.alloc(u8, value.len);
         mem.copy(u8, result, value);
         return result;
std/buffer.zig
@@ -12,14 +12,14 @@ pub const Buffer = struct {
     list: ArrayList(u8),
 
     /// Must deinitialize with deinit.
-    pub fn init(allocator: &Allocator, m: []const u8) %Buffer {
+    pub fn init(allocator: &Allocator, m: []const u8) !Buffer {
         var self = try initSize(allocator, m.len);
         mem.copy(u8, self.list.items, m);
         return self;
     }
 
     /// Must deinitialize with deinit.
-    pub fn initSize(allocator: &Allocator, size: usize) %Buffer {
+    pub fn initSize(allocator: &Allocator, size: usize) !Buffer {
         var self = initNull(allocator);
         try self.resize(size);
         return self;
@@ -37,7 +37,7 @@ pub const Buffer = struct {
     }
 
     /// Must deinitialize with deinit.
-    pub fn initFromBuffer(buffer: &const Buffer) %Buffer {
+    pub fn initFromBuffer(buffer: &const Buffer) !Buffer {
         return Buffer.init(buffer.list.allocator, buffer.toSliceConst());
     }
 
@@ -80,7 +80,7 @@ pub const Buffer = struct {
         self.list.items[self.len()] = 0;
     }
 
-    pub fn resize(self: &Buffer, new_len: usize) %void {
+    pub fn resize(self: &Buffer, new_len: usize) !void {
         try self.list.resize(new_len + 1);
         self.list.items[self.len()] = 0;
     }
@@ -93,24 +93,24 @@ pub const Buffer = struct {
         return self.list.len - 1;
     }
 
-    pub fn append(self: &Buffer, m: []const u8) %void {
+    pub fn append(self: &Buffer, m: []const u8) !void {
         const old_len = self.len();
         try self.resize(old_len + m.len);
         mem.copy(u8, self.list.toSlice()[old_len..], m);
     }
 
     // TODO: remove, use OutStream for this
-    pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) %void {
+    pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) !void {
         return fmt.format(self, append, format, args);
     }
 
     // TODO: remove, use OutStream for this
-    pub fn appendByte(self: &Buffer, byte: u8) %void {
+    pub fn appendByte(self: &Buffer, byte: u8) !void {
         return self.appendByteNTimes(byte, 1);
     }
 
     // TODO: remove, use OutStream for this
-    pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) %void {
+    pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) !void {
         var prev_size: usize = self.len();
         const new_size = prev_size + count;
         try self.resize(new_size);
@@ -137,7 +137,7 @@ pub const Buffer = struct {
         return mem.eql(u8, self.list.items[start..l], m);
     }
 
-    pub fn replaceContents(self: &const Buffer, m: []const u8) %void {
+    pub fn replaceContents(self: &const Buffer, m: []const u8) !void {
         try self.resize(m.len);
         mem.copy(u8, self.list.toSlice(), m);
     }
std/build.zig
@@ -15,13 +15,6 @@ const BufSet = std.BufSet;
 const BufMap = std.BufMap;
 const fmt_lib = std.fmt;
 
-error ExtraArg;
-error UncleanExit;
-error InvalidStepName;
-error DependencyLoopDetected;
-error NoCompilerFound;
-error NeedAnObject;
-
 pub const Builder = struct {
     uninstall_tls: TopLevelStep,
     install_tls: TopLevelStep,
@@ -242,7 +235,7 @@ pub const Builder = struct {
         self.lib_paths.append(path) catch unreachable;
     }
 
-    pub fn make(self: &Builder, step_names: []const []const u8) %void {
+    pub fn make(self: &Builder, step_names: []const []const u8) !void {
         var wanted_steps = ArrayList(&Step).init(self.allocator);
         defer wanted_steps.deinit();
 
@@ -278,7 +271,7 @@ pub const Builder = struct {
         return &self.uninstall_tls.step;
     }
 
-    fn makeUninstall(uninstall_step: &Step) %void {
+    fn makeUninstall(uninstall_step: &Step) !void {
         const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step);
         const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls);
 
@@ -292,7 +285,7 @@ pub const Builder = struct {
         // TODO remove empty directories
     }
 
-    fn makeOneStep(self: &Builder, s: &Step) %void {
+    fn makeOneStep(self: &Builder, s: &Step) !void {
         if (s.loop_flag) {
             warn("Dependency loop detected:\n  {}\n", s.name);
             return error.DependencyLoopDetected;
@@ -313,7 +306,7 @@ pub const Builder = struct {
         try s.make();
     }
 
-    fn getTopLevelStepByName(self: &Builder, name: []const u8) %&Step {
+    fn getTopLevelStepByName(self: &Builder, name: []const u8) !&Step {
         for (self.top_level_steps.toSliceConst()) |top_level_step| {
             if (mem.eql(u8, top_level_step.step.name, name)) {
                 return &top_level_step.step;
@@ -548,7 +541,7 @@ pub const Builder = struct {
         return self.invalid_user_input;
     }
 
-    fn spawnChild(self: &Builder, argv: []const []const u8) %void {
+    fn spawnChild(self: &Builder, argv: []const []const u8) !void {
         return self.spawnChildEnvMap(null, &self.env_map, argv);
     }
 
@@ -595,7 +588,7 @@ pub const Builder = struct {
         }
     }
 
-    pub fn makePath(self: &Builder, path: []const u8) %void {
+    pub fn makePath(self: &Builder, path: []const u8) !void {
         os.makePath(self.allocator, self.pathFromRoot(path)) catch |err| {
             warn("Unable to create path {}: {}\n", path, @errorName(err));
             return err;
@@ -630,11 +623,11 @@ pub const Builder = struct {
         self.installed_files.append(full_path) catch unreachable;
     }
 
-    fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) %void {
+    fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) !void {
         return self.copyFileMode(source_path, dest_path, 0o666);
     }
 
-    fn copyFileMode(self: &Builder, source_path: []const u8, dest_path: []const u8, mode: usize) %void {
+    fn copyFileMode(self: &Builder, source_path: []const u8, dest_path: []const u8, mode: usize) !void {
         if (self.verbose) {
             warn("cp {} {}\n", source_path, dest_path);
         }
@@ -672,7 +665,7 @@ pub const Builder = struct {
         }
     }
 
-    pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) %[]const u8 {
+    pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
         // TODO report error for ambiguous situations
         const exe_extension = (Target { .Native = {}}).exeFileExt();
         for (self.search_prefixes.toSliceConst()) |search_prefix| {
@@ -721,7 +714,7 @@ pub const Builder = struct {
         return error.FileNotFound;
     }
 
-    pub fn exec(self: &Builder, argv: []const []const u8) %[]u8 {
+    pub fn exec(self: &Builder, argv: []const []const u8) ![]u8 {
         const max_output_size = 100 * 1024;
         const result = try os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size);
         switch (result.term) {
@@ -1180,12 +1173,12 @@ pub const LibExeObjStep = struct {
         self.disable_libc = disable;
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(LibExeObjStep, "step", step);
         return if (self.is_zig) self.makeZig() else self.makeC();
     }
 
-    fn makeZig(self: &LibExeObjStep) %void {
+    fn makeZig(self: &LibExeObjStep) !void {
         const builder = self.builder;
 
         assert(self.is_zig);
@@ -1396,7 +1389,7 @@ pub const LibExeObjStep = struct {
         }
     }
 
-    fn makeC(self: &LibExeObjStep) %void {
+    fn makeC(self: &LibExeObjStep) !void {
         const builder = self.builder;
 
         const cc = builder.getCCExe();
@@ -1687,7 +1680,7 @@ pub const TestStep = struct {
         self.exec_cmd_args = args;
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(TestStep, "step", step);
         const builder = self.builder;
 
@@ -1796,7 +1789,7 @@ pub const CommandStep = struct {
         return self;
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(CommandStep, "step", step);
 
         const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root;
@@ -1836,7 +1829,7 @@ const InstallArtifactStep = struct {
         return self;
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(Self, "step", step);
         const builder = self.builder;
 
@@ -1868,7 +1861,7 @@ pub const InstallFileStep = struct {
         };
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(InstallFileStep, "step", step);
         try self.builder.copyFile(self.src_path, self.dest_path);
     }
@@ -1889,7 +1882,7 @@ pub const WriteFileStep = struct {
         };
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(WriteFileStep, "step", step);
         const full_path = self.builder.pathFromRoot(self.file_path);
         const full_path_dir = os.path.dirname(full_path);
@@ -1917,7 +1910,7 @@ pub const LogStep = struct {
         };
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(LogStep, "step", step);
         warn("{}", self.data);
     }
@@ -1936,7 +1929,7 @@ pub const RemoveDirStep = struct {
         };
     }
 
-    fn make(step: &Step) %void {
+    fn make(step: &Step) !void {
         const self = @fieldParentPtr(RemoveDirStep, "step", step);
 
         const full_path = self.builder.pathFromRoot(self.dir_path);
@@ -1967,7 +1960,7 @@ pub const Step = struct {
         return init(name, allocator, makeNoOp);
     }
 
-    pub fn make(self: &Step) %void {
+    pub fn make(self: &Step) !void {
         if (self.done_flag)
             return;
 
std/cstr.zig
@@ -42,7 +42,7 @@ fn testCStrFnsImpl() void {
 /// Returns a mutable slice with exactly the same size which is guaranteed to
 /// have a null byte after it.
 /// Caller owns the returned memory.
-pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) %[]u8 {
+pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) ![]u8 {
     const result = try allocator.alloc(u8, slice.len + 1);
     mem.copy(u8, result, slice);
     result[slice.len] = 0;
@@ -56,7 +56,7 @@ pub const NullTerminated2DArray = struct {
 
     /// Takes N lists of strings, concatenates the lists together, and adds a null terminator
     /// Caller must deinit result
-    pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) %NullTerminated2DArray {
+    pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) !NullTerminated2DArray {
         var new_len: usize = 1; // 1 for the list null
         var byte_count: usize = 0;
         for (slices) |slice| {
std/elf.zig
@@ -6,8 +6,6 @@ const mem = std.mem;
 const debug = std.debug;
 const InStream = std.stream.InStream;
 
-error InvalidFormat;
-
 pub const SHT_NULL = 0;
 pub const SHT_PROGBITS = 1;
 pub const SHT_SYMTAB = 2;
@@ -81,14 +79,14 @@ pub const Elf = struct {
     prealloc_file: io.File,
 
     /// Call close when done.
-    pub fn openPath(elf: &Elf, allocator: &mem.Allocator, path: []const u8) %void {
+    pub fn openPath(elf: &Elf, allocator: &mem.Allocator, path: []const u8) !void {
         try elf.prealloc_file.open(path);
         try elf.openFile(allocator, &elf.prealloc_file);
         elf.auto_close_stream = true;
     }
 
     /// Call close when done.
-    pub fn openFile(elf: &Elf, allocator: &mem.Allocator, file: &io.File) %void {
+    pub fn openFile(elf: &Elf, allocator: &mem.Allocator, file: &io.File) !void {
         elf.allocator = allocator;
         elf.in_file = file;
         elf.auto_close_stream = false;
@@ -239,7 +237,7 @@ pub const Elf = struct {
             elf.in_file.close();
     }
 
-    pub fn findSection(elf: &Elf, name: []const u8) %?&SectionHeader {
+    pub fn findSection(elf: &Elf, name: []const u8) !?&SectionHeader {
         var file_stream = io.FileInStream.init(elf.in_file);
         const in = &file_stream.stream;
 
@@ -263,7 +261,7 @@ pub const Elf = struct {
         return null;
     }
 
-    pub fn seekToSection(elf: &Elf, elf_section: &SectionHeader) %void {
+    pub fn seekToSection(elf: &Elf, elf_section: &SectionHeader) !void {
         try elf.in_file.seekTo(elf_section.offset);
     }
 };
std/hash_map.zig
@@ -80,7 +80,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
         }
 
         /// Returns the value that was already there.
-        pub fn put(hm: &Self, key: K, value: &const V) %?V {
+        pub fn put(hm: &Self, key: K, value: &const V) !?V {
             if (hm.entries.len == 0) {
                 try hm.initCapacity(16);
             }
@@ -151,7 +151,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
             };
         }
 
-        fn initCapacity(hm: &Self, capacity: usize) %void {
+        fn initCapacity(hm: &Self, capacity: usize) !void {
             hm.entries = try hm.allocator.alloc(Entry, capacity);
             hm.size = 0;
             hm.max_distance_from_start_index = 0;
std/heap.zig
@@ -9,8 +9,6 @@ const c = std.c;
 
 const Allocator = mem.Allocator;
 
-error OutOfMemory;
-
 pub const c_allocator = &c_allocator_state;
 var c_allocator_state = Allocator {
     .allocFn = cAlloc,
@@ -18,14 +16,14 @@ var c_allocator_state = Allocator {
     .freeFn = cFree,
 };
 
-fn cAlloc(self: &Allocator, n: usize, alignment: u29) %[]u8 {
+fn cAlloc(self: &Allocator, n: usize, alignment: u29) ![]u8 {
     return if (c.malloc(usize(n))) |buf|
         @ptrCast(&u8, buf)[0..n]
     else
         error.OutOfMemory;
 }
 
-fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
+fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
     const old_ptr = @ptrCast(&c_void, old_mem.ptr);
     if (c.realloc(old_ptr, new_size)) |buf| {
         return @ptrCast(&u8, buf)[0..new_size];
@@ -47,7 +45,7 @@ pub const IncrementingAllocator = struct {
     end_index: usize,
     heap_handle: if (builtin.os == Os.windows) os.windows.HANDLE else void,
 
-    fn init(capacity: usize) %IncrementingAllocator {
+    fn init(capacity: usize) !IncrementingAllocator {
         switch (builtin.os) {
             Os.linux, Os.macosx, Os.ios => {
                 const p = os.posix;
@@ -105,7 +103,7 @@ pub const IncrementingAllocator = struct {
         return self.bytes.len - self.end_index;
     }
 
-    fn alloc(allocator: &Allocator, n: usize, alignment: u29) %[]u8 {
+    fn alloc(allocator: &Allocator, n: usize, alignment: u29) ![]u8 {
         const self = @fieldParentPtr(IncrementingAllocator, "allocator", allocator);
         const addr = @ptrToInt(&self.bytes[self.end_index]);
         const rem = @rem(addr, alignment);
@@ -120,7 +118,7 @@ pub const IncrementingAllocator = struct {
         return result;
     }
 
-    fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
+    fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
         if (new_size <= old_mem.len) {
             return old_mem[0..new_size];
         } else {
std/io.zig
@@ -26,31 +26,7 @@ test "import io tests" {
     }
 }
 
-/// The function received invalid input at runtime. An Invalid error means a
-/// bug in the program that called the function.
-error Invalid;
-
-error DiskQuota;
-error FileTooBig;
-error Io;
-error NoSpaceLeft;
-error BadPerm;
-error BrokenPipe;
-error BadFd;
-error IsDir;
-error NotDir;
-error SymLinkLoop;
-error ProcessFdQuotaExceeded;
-error SystemFdQuotaExceeded;
-error NameTooLong;
-error NoDevice;
-error PathNotFound;
-error OutOfMemory;
-error Unseekable;
-error EndOfFile;
-error FilePosLargerThanPointerRange;
-
-pub fn getStdErr() %File {
+pub fn getStdErr() !File {
     const handle = if (is_windows)
         try os.windowsGetStdHandle(system.STD_ERROR_HANDLE)
     else if (is_posix)
@@ -60,7 +36,7 @@ pub fn getStdErr() %File {
     return File.openHandle(handle);
 }
 
-pub fn getStdOut() %File {
+pub fn getStdOut() !File {
     const handle = if (is_windows)
         try os.windowsGetStdHandle(system.STD_OUTPUT_HANDLE)
     else if (is_posix)
@@ -70,7 +46,7 @@ pub fn getStdOut() %File {
     return File.openHandle(handle);
 }
 
-pub fn getStdIn() %File {
+pub fn getStdIn() !File {
     const handle = if (is_windows)
         try os.windowsGetStdHandle(system.STD_INPUT_HANDLE)
     else if (is_posix)
@@ -94,7 +70,7 @@ pub const FileInStream = struct {
         };
     }
 
-    fn readFn(in_stream: &InStream, buffer: []u8) %usize {
+    fn readFn(in_stream: &InStream, buffer: []u8) !usize {
         const self = @fieldParentPtr(FileInStream, "stream", in_stream);
         return self.file.read(buffer);
     }
@@ -114,7 +90,7 @@ pub const FileOutStream = struct {
         };
     }
 
-    fn writeFn(out_stream: &OutStream, bytes: []const u8) %void {
+    fn writeFn(out_stream: &OutStream, bytes: []const u8) !void {
         const self = @fieldParentPtr(FileOutStream, "stream", out_stream);
         return self.file.write(bytes);
     }
@@ -129,7 +105,7 @@ pub const File = struct {
     /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned.
     /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
     /// Call close to clean up.
-    pub fn openRead(path: []const u8, allocator: ?&mem.Allocator) %File {
+    pub fn openRead(path: []const u8, allocator: ?&mem.Allocator) !File {
         if (is_posix) {
             const flags = system.O_LARGEFILE|system.O_RDONLY;
             const fd = try os.posixOpen(path, flags, 0, allocator);
@@ -144,7 +120,7 @@ pub const File = struct {
     }
 
     /// Calls `openWriteMode` with 0o666 for the mode.
-    pub fn openWrite(path: []const u8, allocator: ?&mem.Allocator) %File {
+    pub fn openWrite(path: []const u8, allocator: ?&mem.Allocator) !File {
         return openWriteMode(path, 0o666, allocator);
 
     }
@@ -154,7 +130,7 @@ pub const File = struct {
     /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned.
     /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
     /// Call close to clean up.
-    pub fn openWriteMode(path: []const u8, mode: usize, allocator: ?&mem.Allocator) %File {
+    pub fn openWriteMode(path: []const u8, mode: usize, allocator: ?&mem.Allocator) !File {
         if (is_posix) {
             const flags = system.O_LARGEFILE|system.O_WRONLY|system.O_CREAT|system.O_CLOEXEC|system.O_TRUNC;
             const fd = try os.posixOpen(path, flags, mode, allocator);
@@ -189,7 +165,7 @@ pub const File = struct {
         return os.isTty(self.handle);
     }
 
-    pub fn seekForward(self: &File, amount: isize) %void {
+    pub fn seekForward(self: &File, amount: isize) !void {
         switch (builtin.os) {
             Os.linux, Os.macosx, Os.ios => {
                 const result = system.lseek(self.handle, amount, system.SEEK_CUR);
@@ -218,7 +194,7 @@ pub const File = struct {
         }
     }
 
-    pub fn seekTo(self: &File, pos: usize) %void {
+    pub fn seekTo(self: &File, pos: usize) !void {
         switch (builtin.os) {
             Os.linux, Os.macosx, Os.ios => {
                 const ipos = try math.cast(isize, pos);
@@ -249,7 +225,7 @@ pub const File = struct {
         }
     }
 
-    pub fn getPos(self: &File) %usize {
+    pub fn getPos(self: &File) !usize {
         switch (builtin.os) {
             Os.linux, Os.macosx, Os.ios => {
                 const result = system.lseek(self.handle, 0, system.SEEK_CUR);
@@ -289,7 +265,7 @@ pub const File = struct {
         }
     }
 
-    pub fn getEndPos(self: &File) %usize {
+    pub fn getEndPos(self: &File) !usize {
         if (is_posix) {
             var stat: system.Stat = undefined;
             const err = system.getErrno(system.fstat(self.handle, &stat));
@@ -318,7 +294,7 @@ pub const File = struct {
         }
     }
 
-    pub fn read(self: &File, buffer: []u8) %usize {
+    pub fn read(self: &File, buffer: []u8) !usize {
         if (is_posix) {
             var index: usize = 0;
             while (index < buffer.len) {
@@ -360,7 +336,7 @@ pub const File = struct {
         }
     }
 
-    fn write(self: &File, bytes: []const u8) %void {
+    fn write(self: &File, bytes: []const u8) !void {
         if (is_posix) {
             try os.posixWrite(self.handle, bytes);
         } else if (is_windows) {
@@ -371,19 +347,16 @@ pub const File = struct {
     }
 };
 
-error StreamTooLong;
-error EndOfStream;
-
 pub const InStream = struct {
     /// Return the number of bytes read. If the number read is smaller than buf.len, it
     /// means the stream reached the end. Reaching the end of a stream is not an error
     /// condition.
-    readFn: fn(self: &InStream, buffer: []u8) %usize,
+    readFn: fn(self: &InStream, buffer: []u8) !usize,
 
     /// Replaces `buffer` contents by reading from the stream until it is finished.
     /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and
     /// the contents read from the stream are lost.
-    pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) %void {
+    pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) !void {
         try buffer.resize(0);
 
         var actual_buf_len: usize = 0;
@@ -408,7 +381,7 @@ pub const InStream = struct {
     /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
     /// Caller owns returned memory.
     /// If this function returns an error, the contents from the stream read so far are lost.
-    pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) %[]u8 {
+    pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) ![]u8 {
         var buf = Buffer.initNull(allocator);
         defer buf.deinit();
 
@@ -420,7 +393,7 @@ pub const InStream = struct {
     /// Does not include the delimiter in the result.
     /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents
     /// read from the stream so far are lost.
-    pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) %void {
+    pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) !void {
         try buf.resize(0);
 
         while (true) {
@@ -443,7 +416,7 @@ pub const InStream = struct {
     /// Caller owns returned memory.
     /// If this function returns an error, the contents from the stream read so far are lost.
     pub fn readUntilDelimiterAlloc(self: &InStream, allocator: &mem.Allocator,
-        delimiter: u8, max_size: usize) %[]u8
+        delimiter: u8, max_size: usize) ![]u8
     {
         var buf = Buffer.initNull(allocator);
         defer buf.deinit();
@@ -455,43 +428,43 @@ pub const InStream = struct {
     /// Returns the number of bytes read. If the number read is smaller than buf.len, it
     /// means the stream reached the end. Reaching the end of a stream is not an error
     /// condition.
-    pub fn read(self: &InStream, buffer: []u8) %usize {
+    pub fn read(self: &InStream, buffer: []u8) !usize {
         return self.readFn(self, buffer);
     }
 
     /// Same as `read` but end of stream returns `error.EndOfStream`.
-    pub fn readNoEof(self: &InStream, buf: []u8) %void {
+    pub fn readNoEof(self: &InStream, buf: []u8) !void {
         const amt_read = try self.read(buf);
         if (amt_read < buf.len) return error.EndOfStream;
     }
 
     /// Reads 1 byte from the stream or returns `error.EndOfStream`.
-    pub fn readByte(self: &InStream) %u8 {
+    pub fn readByte(self: &InStream) !u8 {
         var result: [1]u8 = undefined;
         try self.readNoEof(result[0..]);
         return result[0];
     }
 
     /// Same as `readByte` except the returned byte is signed.
-    pub fn readByteSigned(self: &InStream) %i8 {
+    pub fn readByteSigned(self: &InStream) !i8 {
         return @bitCast(i8, try self.readByte());
     }
 
-    pub fn readIntLe(self: &InStream, comptime T: type) %T {
+    pub fn readIntLe(self: &InStream, comptime T: type) !T {
         return self.readInt(builtin.Endian.Little, T);
     }
 
-    pub fn readIntBe(self: &InStream, comptime T: type) %T {
+    pub fn readIntBe(self: &InStream, comptime T: type) !T {
         return self.readInt(builtin.Endian.Big, T);
     }
 
-    pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) %T {
+    pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) !T {
         var bytes: [@sizeOf(T)]u8 = undefined;
         try self.readNoEof(bytes[0..]);
         return mem.readInt(bytes, T, endian);
     }
 
-    pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) %T {
+    pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) !T {
         assert(size <= @sizeOf(T));
         assert(size <= 8);
         var input_buf: [8]u8 = undefined;
@@ -504,22 +477,23 @@ pub const InStream = struct {
 };
 
 pub const OutStream = struct {
-    writeFn: fn(self: &OutStream, bytes: []const u8) %void,
+    // TODO allow specifying the error set
+    writeFn: fn(self: &OutStream, bytes: []const u8) error!void,
 
-    pub fn print(self: &OutStream, comptime format: []const u8, args: ...) %void {
-        return std.fmt.format(self, self.writeFn, format, args);
+    pub fn print(self: &OutStream, comptime format: []const u8, args: ...) !void {
+        return std.fmt.format(self, error, self.writeFn, format, args);
     }
 
-    pub fn write(self: &OutStream, bytes: []const u8) %void {
+    pub fn write(self: &OutStream, bytes: []const u8) !void {
         return self.writeFn(self, bytes);
     }
 
-    pub fn writeByte(self: &OutStream, byte: u8) %void {
+    pub fn writeByte(self: &OutStream, byte: u8) !void {
         const slice = (&byte)[0..1];
         return self.writeFn(self, slice);
     }
 
-    pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) %void {
+    pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) !void {
         const slice = (&byte)[0..1];
         var i: usize = 0;
         while (i < n) : (i += 1) {
@@ -532,19 +506,19 @@ pub const OutStream = struct {
 /// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed
 /// size buffer is too small, and the provided allocator is null, `error.NameTooLong` is returned.
 /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
-pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) %void {
+pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) !void {
     var file = try File.openWrite(path, allocator);
     defer file.close();
     try file.write(data);
 }
 
 /// On success, caller owns returned buffer.
-pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) %[]u8 {
+pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) ![]u8 {
     return readFileAllocExtra(path, allocator, 0);
 }
 /// On success, caller owns returned buffer.
 /// Allocates extra_len extra bytes at the end of the file buffer, which are uninitialized.
-pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len: usize) %[]u8 {
+pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len: usize) ![]u8 {
     var file = try File.openRead(path, allocator);
     defer file.close();
 
@@ -589,7 +563,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) type {
             };
         }
 
-        fn readFn(in_stream: &InStream, dest: []u8) %usize {
+        fn readFn(in_stream: &InStream, dest: []u8) !usize {
             const self = @fieldParentPtr(Self, "stream", in_stream);
 
             var dest_index: usize = 0;
@@ -652,7 +626,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) type {
             };
         }
 
-        pub fn flush(self: &Self) %void {
+        pub fn flush(self: &Self) !void {
             if (self.index == 0)
                 return;
 
@@ -660,7 +634,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) type {
             self.index = 0;
         }
 
-        fn writeFn(out_stream: &OutStream, bytes: []const u8) %void {
+        fn writeFn(out_stream: &OutStream, bytes: []const u8) !void {
             const self = @fieldParentPtr(Self, "stream", out_stream);
 
             if (bytes.len >= self.buffer.len) {
@@ -698,7 +672,7 @@ pub const BufferOutStream = struct {
         };
     }
 
-    fn writeFn(out_stream: &OutStream, bytes: []const u8) %void {
+    fn writeFn(out_stream: &OutStream, bytes: []const u8) !void {
         const self = @fieldParentPtr(BufferOutStream, "stream", out_stream);
         return self.buffer.append(bytes);
     }
std/linked_list.zig
@@ -190,7 +190,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
         ///
         /// Returns:
         ///     A pointer to the new node.
-        pub fn allocateNode(list: &Self, allocator: &Allocator) %&Node {
+        pub fn allocateNode(list: &Self, allocator: &Allocator) !&Node {
             comptime assert(!isIntrusive());
             return allocator.create(Node);
         }
@@ -213,7 +213,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
         ///
         /// Returns:
         ///     A pointer to the new node.
-        pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) %&Node {
+        pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) !&Node {
             comptime assert(!isIntrusive());
             var node = try list.allocateNode(allocator);
             *node = Node.init(data);
std/mem.zig
@@ -4,13 +4,13 @@ const assert = debug.assert;
 const math = std.math;
 const builtin = @import("builtin");
 
-error OutOfMemory;
-
 pub const Allocator = struct {
+    const Errors = error {OutOfMemory};
+
     /// Allocate byte_count bytes and return them in a slice, with the
     /// slice's pointer aligned at least to alignment bytes.
     /// The returned newly allocated memory is undefined.
-    allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) %[]u8,
+    allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) Errors![]u8,
 
     /// If `new_byte_count > old_mem.len`:
     /// * `old_mem.len` is the same as what was returned from allocFn or reallocFn.
@@ -21,12 +21,12 @@ pub const Allocator = struct {
     /// * alignment <= alignment of old_mem.ptr
     ///
     /// The returned newly allocated memory is undefined.
-    reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) %[]u8,
+    reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Errors![]u8,
 
     /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
     freeFn: fn (self: &Allocator, old_mem: []u8) void,
 
-    fn create(self: &Allocator, comptime T: type) %&T {
+    fn create(self: &Allocator, comptime T: type) !&T {
         const slice = try self.alloc(T, 1);
         return &slice[0];
     }
@@ -35,7 +35,7 @@ pub const Allocator = struct {
         self.free(ptr[0..1]);
     }
 
-    fn alloc(self: &Allocator, comptime T: type, n: usize) %[]T {
+    fn alloc(self: &Allocator, comptime T: type, n: usize) ![]T {
         return self.alignedAlloc(T, @alignOf(T), n);
     }
 
@@ -51,7 +51,7 @@ pub const Allocator = struct {
         return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
     }
 
-    fn realloc(self: &Allocator, comptime T: type, old_mem: []T, n: usize) %[]T {
+    fn realloc(self: &Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {
         return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
     }
 
@@ -123,7 +123,7 @@ pub const FixedBufferAllocator = struct {
         };
     }
 
-    fn alloc(allocator: &Allocator, n: usize, alignment: u29) %[]u8 {
+    fn alloc(allocator: &Allocator, n: usize, alignment: u29) ![]u8 {
         const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator);
         const addr = @ptrToInt(&self.buffer[self.end_index]);
         const rem = @rem(addr, alignment);
@@ -138,7 +138,7 @@ pub const FixedBufferAllocator = struct {
         return result;
     }
 
-    fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 {
+    fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
         if (new_size <= old_mem.len) {
             return old_mem[0..new_size];
         } else {
@@ -197,7 +197,7 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
 }
 
 /// Copies ::m to newly allocated memory. Caller is responsible to free it.
-pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) %[]T {
+pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) ![]T {
     const new_buf = try allocator.alloc(T, m.len);
     copy(T, new_buf, m);
     return new_buf;
@@ -428,7 +428,7 @@ const SplitIterator = struct {
 
 /// Naively combines a series of strings with a separator.
 /// Allocates memory for the result, which must be freed by the caller.
-pub fn join(allocator: &Allocator, sep: u8, strings: ...) %[]u8 {
+pub fn join(allocator: &Allocator, sep: u8, strings: ...) ![]u8 {
     comptime assert(strings.len >= 1);
     var total_strings_len: usize = strings.len; // 1 sep per string
     {
std/net.zig
@@ -5,19 +5,10 @@ const endian = std.endian;
 
 // TODO don't trust this file, it bit rotted. start over
 
-error SigInterrupt;
-error Io;
-error TimedOut;
-error ConnectionReset;
-error ConnectionRefused;
-error OutOfMemory;
-error NotSocket;
-error BadFd;
-
 const Connection = struct {
     socket_fd: i32,
 
-    pub fn send(c: Connection, buf: []const u8) %usize {
+    pub fn send(c: Connection, buf: []const u8) !usize {
         const send_ret = linux.sendto(c.socket_fd, buf.ptr, buf.len, 0, null, 0);
         const send_err = linux.getErrno(send_ret);
         switch (send_err) {
@@ -31,7 +22,7 @@ const Connection = struct {
         }
     }
 
-    pub fn recv(c: Connection, buf: []u8) %[]u8 {
+    pub fn recv(c: Connection, buf: []u8) ![]u8 {
         const recv_ret = linux.recvfrom(c.socket_fd, buf.ptr, buf.len, 0, null, null);
         const recv_err = linux.getErrno(recv_ret);
         switch (recv_err) {
@@ -48,7 +39,7 @@ const Connection = struct {
         }
     }
 
-    pub fn close(c: Connection) %void {
+    pub fn close(c: Connection) !void {
         switch (linux.getErrno(linux.close(c.socket_fd))) {
             0 => return,
             linux.EBADF => unreachable,
@@ -66,7 +57,7 @@ const Address = struct {
     sort_key: i32,
 };
 
-pub fn lookup(hostname: []const u8, out_addrs: []Address) %[]Address {
+pub fn lookup(hostname: []const u8, out_addrs: []Address) ![]Address {
     if (hostname.len == 0) {
 
         unreachable; // TODO
@@ -75,7 +66,7 @@ pub fn lookup(hostname: []const u8, out_addrs: []Address) %[]Address {
     unreachable; // TODO
 }
 
-pub fn connectAddr(addr: &Address, port: u16) %Connection {
+pub fn connectAddr(addr: &Address, port: u16) !Connection {
     const socket_ret = linux.socket(addr.family, linux.SOCK_STREAM, linux.PROTO_tcp);
     const socket_err = linux.getErrno(socket_ret);
     if (socket_err > 0) {
@@ -118,7 +109,7 @@ pub fn connectAddr(addr: &Address, port: u16) %Connection {
     };
 }
 
-pub fn connect(hostname: []const u8, port: u16) %Connection {
+pub fn connect(hostname: []const u8, port: u16) !Connection {
     var addrs_buf: [1]Address = undefined;
     const addrs_slice = try lookup(hostname, addrs_buf[0..]);
     const main_addr = &addrs_slice[0];
@@ -126,9 +117,7 @@ pub fn connect(hostname: []const u8, port: u16) %Connection {
     return connectAddr(main_addr, port);
 }
 
-error InvalidIpLiteral;
-
-pub fn parseIpLiteral(buf: []const u8) %Address {
+pub fn parseIpLiteral(buf: []const u8) !Address {
 
     return error.InvalidIpLiteral;
 }
@@ -146,12 +135,7 @@ fn hexDigit(c: u8) u8 {
     }
 }
 
-error InvalidChar;
-error Overflow;
-error JunkAtEnd;
-error Incomplete;
-
-fn parseIp6(buf: []const u8) %Address {
+fn parseIp6(buf: []const u8) !Address {
     var result: Address = undefined;
     result.family = linux.AF_INET6;
     result.scope_id = 0;
@@ -232,7 +216,7 @@ fn parseIp6(buf: []const u8) %Address {
     return error.Incomplete;
 }
 
-fn parseIp4(buf: []const u8) %u32 {
+fn parseIp4(buf: []const u8) !u32 {
     var result: u32 = undefined;
     const out_ptr = ([]u8)((&result)[0..1]);
 
std/unicode.zig
@@ -1,11 +1,9 @@
 const std = @import("./index.zig");
 
-error Utf8InvalidStartByte;
-
 /// Given the first byte of a UTF-8 codepoint,
 /// returns a number 1-4 indicating the total length of the codepoint in bytes.
 /// If this byte does not match the form of a UTF-8 start byte, returns Utf8InvalidStartByte.
-pub fn utf8ByteSequenceLength(first_byte: u8) %u3 {
+pub fn utf8ByteSequenceLength(first_byte: u8) !u3 {
     if (first_byte < 0b10000000) return u3(1);
     if (first_byte & 0b11100000 == 0b11000000) return u3(2);
     if (first_byte & 0b11110000 == 0b11100000) return u3(3);
@@ -13,16 +11,11 @@ pub fn utf8ByteSequenceLength(first_byte: u8) %u3 {
     return error.Utf8InvalidStartByte;
 }
 
-error Utf8OverlongEncoding;
-error Utf8ExpectedContinuation;
-error Utf8EncodesSurrogateHalf;
-error Utf8CodepointTooLarge;
-
 /// Decodes the UTF-8 codepoint encoded in the given slice of bytes.
 /// bytes.len must be equal to utf8ByteSequenceLength(bytes[0]) catch unreachable.
 /// If you already know the length at comptime, you can call one of
 /// utf8Decode2,utf8Decode3,utf8Decode4 directly instead of this function.
-pub fn utf8Decode(bytes: []const u8) %u32 {
+pub fn utf8Decode(bytes: []const u8) !u32 {
     return switch (bytes.len) {
         1 => u32(bytes[0]),
         2 => utf8Decode2(bytes),
@@ -31,7 +24,7 @@ pub fn utf8Decode(bytes: []const u8) %u32 {
         else => unreachable,
     };
 }
-pub fn utf8Decode2(bytes: []const u8) %u32 {
+pub fn utf8Decode2(bytes: []const u8) !u32 {
     std.debug.assert(bytes.len == 2);
     std.debug.assert(bytes[0] & 0b11100000 == 0b11000000);
     var value: u32 = bytes[0] & 0b00011111;
@@ -44,7 +37,7 @@ pub fn utf8Decode2(bytes: []const u8) %u32 {
 
     return value;
 }
-pub fn utf8Decode3(bytes: []const u8) %u32 {
+pub fn utf8Decode3(bytes: []const u8) !u32 {
     std.debug.assert(bytes.len == 3);
     std.debug.assert(bytes[0] & 0b11110000 == 0b11100000);
     var value: u32 = bytes[0] & 0b00001111;
@@ -62,7 +55,7 @@ pub fn utf8Decode3(bytes: []const u8) %u32 {
 
     return value;
 }
-pub fn utf8Decode4(bytes: []const u8) %u32 {
+pub fn utf8Decode4(bytes: []const u8) !u32 {
     std.debug.assert(bytes.len == 4);
     std.debug.assert(bytes[0] & 0b11111000 == 0b11110000);
     var value: u32 = bytes[0] & 0b00000111;
@@ -85,7 +78,6 @@ pub fn utf8Decode4(bytes: []const u8) %u32 {
     return value;
 }
 
-error UnexpectedEof;
 test "valid utf8" {
     testValid("\x00", 0x0);
     testValid("\x20", 0x20);
@@ -161,7 +153,7 @@ fn testValid(bytes: []const u8, expected_codepoint: u32) void {
     std.debug.assert((testDecode(bytes) catch unreachable) == expected_codepoint);
 }
 
-fn testDecode(bytes: []const u8) %u32 {
+fn testDecode(bytes: []const u8) !u32 {
     const length = try utf8ByteSequenceLength(bytes[0]);
     if (bytes.len < length) return error.UnexpectedEof;
     std.debug.assert(bytes.len == length);
test/cases/cast.zig
@@ -32,7 +32,6 @@ fn funcWithConstPtrPtr(x: &const &i32) void {
     **x += 1;
 }
 
-error ItBroke;
 test "explicit cast from integer to error type" {
     testCastIntToErr(error.ItBroke);
     comptime testCastIntToErr(error.ItBroke);
@@ -110,11 +109,11 @@ test "return null from fn() %?&T" {
     const b = returnNullLitFromMaybeTypeErrorRef();
     assert((try a) == null and (try b) == null);
 }
-fn returnNullFromMaybeTypeErrorRef() %?&A {
+fn returnNullFromMaybeTypeErrorRef() !?&A {
     const a: ?&A = null;
     return a;
 }
-fn returnNullLitFromMaybeTypeErrorRef() %?&A {
+fn returnNullLitFromMaybeTypeErrorRef() !?&A {
     return null;
 }
 
@@ -170,7 +169,7 @@ fn testCastZeroArrayToErrSliceMut() void {
     assert((gimmeErrOrSlice() catch unreachable).len == 0);
 }
 
-fn gimmeErrOrSlice() %[]u8 {
+fn gimmeErrOrSlice() ![]u8 {
     return []u8{};
 }
 
@@ -188,7 +187,7 @@ test "peer type resolution: [0]u8, []const u8, and %[]u8" {
         assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
     }
 }
-fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) %[]u8 {
+fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) ![]u8 {
     if (a) {
         return []u8{};
     }
@@ -238,14 +237,13 @@ test "peer type resolution: error and [N]T" {
     comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
 }
 
-error BadValue;
-//fn testPeerErrorAndArray(x: u8) %[]const u8 {
+//fn testPeerErrorAndArray(x: u8) ![]const u8 {
 //    return switch (x) {
 //        0x00 => "OK",
 //        else => error.BadValue,
 //    };
 //}
-fn testPeerErrorAndArray2(x: u8) %[]const u8 {
+fn testPeerErrorAndArray2(x: u8) ![]const u8 {
     return switch (x) {
         0x00 => "OK",
         0x01 => "OKK",
test/cases/defer.zig
@@ -3,9 +3,7 @@ const assert = @import("std").debug.assert;
 var result: [3]u8 = undefined;
 var index: usize = undefined;
 
-error FalseNotAllowed;
-
-fn runSomeErrorDefers(x: bool) %bool {
+fn runSomeErrorDefers(x: bool) !bool {
     index = 0;
     defer {result[index] = 'a'; index += 1;}
     errdefer {result[index] = 'b'; index += 1;}
test/cases/enum_with_members.zig
@@ -6,7 +6,7 @@ const ET = union(enum) {
     SINT: i32,
     UINT: u32,
 
-    pub fn print(a: &const ET, buf: []u8) %usize {
+    pub fn print(a: &const ET, buf: []u8) !usize {
         return switch (*a) {
             ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
             ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
test/cases/error.zig
@@ -1,16 +1,16 @@
 const assert = @import("std").debug.assert;
 const mem = @import("std").mem;
 
-pub fn foo() %i32 {
+pub fn foo() !i32 {
     const x = try bar();
     return x + 1;
 }
 
-pub fn bar() %i32 {
+pub fn bar() !i32 {
     return 13;
 }
 
-pub fn baz() %i32 {
+pub fn baz() !i32 {
     const y = foo() catch 1234;
     return y + 1;
 }
@@ -19,7 +19,6 @@ test "error wrapping" {
     assert((baz() catch unreachable) == 15);
 }
 
-error ItBroke;
 fn gimmeItBroke() []const u8 {
     return @errorName(error.ItBroke);
 }
@@ -28,8 +27,6 @@ test "@errorName" {
     assert(mem.eql(u8, @errorName(error.AnError), "AnError"));
     assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
 }
-error AnError;
-error ALongerErrorName;
 
 
 test "error values" {
@@ -37,16 +34,11 @@ test "error values" {
     const b = i32(error.err2);
     assert(a != b);
 }
-error err1;
-error err2;
 
 
 test "redefinition of error values allowed" {
     shouldBeNotEqual(error.AnError, error.SecondError);
 }
-error AnError;
-error AnError;
-error SecondError;
 fn shouldBeNotEqual(a: error, b: error) void {
     if (a == b) unreachable;
 }
@@ -58,8 +50,7 @@ test "error binary operator" {
     assert(a == 3);
     assert(b == 10);
 }
-error ItBroke;
-fn errBinaryOperatorG(x: bool) %isize {
+fn errBinaryOperatorG(x: bool) !isize {
     return if (x) error.ItBroke else isize(10);
 }
 
@@ -75,11 +66,11 @@ test "error return in assignment" {
     doErrReturnInAssignment() catch unreachable;
 }
 
-fn doErrReturnInAssignment() %void {
+fn doErrReturnInAssignment() !void {
     var x : i32 = undefined;
     x = try makeANonErr();
 }
 
-fn makeANonErr() %i32 {
+fn makeANonErr() !i32 {
     return 1;
 }
test/cases/ir_block_deps.zig
@@ -1,6 +1,6 @@
 const assert = @import("std").debug.assert;
 
-fn foo(id: u64) %i32 {
+fn foo(id: u64) !i32 {
     return switch (id) {
         1 => getErrInt(),
         2 => {
@@ -13,8 +13,6 @@ fn foo(id: u64) %i32 {
 
 fn getErrInt() %i32 { return 0; }
 
-error ItBroke;
-
 test "ir block deps" {
     assert((foo(1) catch unreachable) == 0);
     assert((foo(2) catch unreachable) == 0);
test/cases/misc.zig
@@ -262,7 +262,7 @@ test "generic malloc free" {
     memFree(u8, a);
 }
 const some_mem : [100]u8 = undefined;
-fn memAlloc(comptime T: type, n: usize) %[]T {
+fn memAlloc(comptime T: type, n: usize) ![]T {
     return @ptrCast(&T, &some_mem[0])[0..n];
 }
 fn memFree(comptime T: type, memory: []T) void { }
@@ -419,7 +419,7 @@ test "cast slice to u8 slice" {
 test "pointer to void return type" {
     testPointerToVoidReturnType() catch unreachable;
 }
-fn testPointerToVoidReturnType() %void {
+fn testPointerToVoidReturnType() !void {
     const a = testPointerToVoidReturnType2();
     return *a;
 }
test/cases/switch.zig
@@ -225,7 +225,7 @@ fn switchWithUnreachable(x: i32) i32 {
     return 10;
 }
 
-fn return_a_number() %i32 {
+fn return_a_number() !i32 {
     return 1;
 }
 
test/cases/switch_prong_err_enum.zig
@@ -2,19 +2,17 @@ const assert = @import("std").debug.assert;
 
 var read_count: u64 = 0;
 
-fn readOnce() %u64 {
+fn readOnce() !u64 {
     read_count += 1;
     return read_count;
 }
 
-error InvalidDebugInfo;
-
 const FormValue = union(enum) {
     Address: u64,
     Other: bool,
 };
 
-fn doThing(form_id: u64) %FormValue {
+fn doThing(form_id: u64) !FormValue {
     return switch (form_id) {
         17 => FormValue { .Address = try readOnce() },
         else => error.InvalidDebugInfo,
test/cases/switch_prong_implicit_cast.zig
@@ -5,9 +5,7 @@ const FormValue = union(enum) {
     Two: bool,
 };
 
-error Whatever;
-
-fn foo(id: u64) %FormValue {
+fn foo(id: u64) !FormValue {
     return switch (id) {
         2 => FormValue { .Two = true },
         1 => FormValue { .One = {} },
test/cases/try.zig
@@ -17,10 +17,7 @@ fn tryOnErrorUnionImpl() void {
     assert(x == 11);
 }
 
-error ItBroke;
-error NoMem;
-error CrappedOut;
-fn returnsTen() %i32 {
+fn returnsTen() !i32 {
     return 10;
 }
 
@@ -32,7 +29,7 @@ test "try without vars" {
     assert(result2 == 1);
 }
 
-fn failIfTrue(ok: bool) %void {
+fn failIfTrue(ok: bool) !void {
     if (ok) {
         return error.ItBroke;
     } else {
test/cases/while.zig
@@ -50,7 +50,7 @@ fn runContinueAndBreakTest() void {
 test "return with implicit cast from while loop" {
     returnWithImplicitCastFromWhileLoopTest() catch unreachable;
 }
-fn returnWithImplicitCastFromWhileLoopTest() %void {
+fn returnWithImplicitCastFromWhileLoopTest() !void {
     while (true) {
         return;
     }
@@ -116,8 +116,7 @@ test "while with error union condition" {
 }
 
 var numbers_left: i32 = undefined;
-error OutOfNumbers;
-fn getNumberOrErr() %i32 {
+fn getNumberOrErr() !i32 {
     return if (numbers_left == 0)
         error.OutOfNumbers
     else x: {
@@ -205,7 +204,6 @@ fn testContinueOuter() void {
 
 fn returnNull() ?i32 { return null; }
 fn returnMaybe(x: i32) ?i32 { return x; }
-error YouWantedAnError;
 fn returnError() %i32 { return error.YouWantedAnError; }
 fn returnSuccess(x: i32) %i32 { return x; }
 fn returnFalse() bool { return false; }
test/standalone/brace_expansion/build.zig
@@ -1,6 +1,6 @@
 const Builder = @import("std").build.Builder;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     const main = b.addTest("main.zig");
     main.setBuildMode(b.standardReleaseOptions());
 
test/standalone/brace_expansion/main.zig
@@ -6,9 +6,6 @@ const assert = debug.assert;
 const Buffer = std.Buffer;
 const ArrayList = std.ArrayList;
 
-error InvalidInput;
-error OutOfMem;
-
 const Token = union(enum) {
     Word: []const u8,
     OpenBrace,
@@ -19,7 +16,7 @@ const Token = union(enum) {
 
 var global_allocator: &mem.Allocator = undefined;
 
-fn tokenize(input:[] const u8) %ArrayList(Token) {
+fn tokenize(input:[] const u8) !ArrayList(Token) {
     const State = enum {
         Start,
         Word,
@@ -71,7 +68,7 @@ const Node = union(enum) {
     Combine: []Node,
 };
 
-fn parse(tokens: &const ArrayList(Token), token_index: &usize) %Node {
+fn parse(tokens: &const ArrayList(Token), token_index: &usize) !Node {
     const first_token = tokens.items[*token_index];
     *token_index += 1;
 
@@ -107,7 +104,7 @@ fn parse(tokens: &const ArrayList(Token), token_index: &usize) %Node {
     }
 }
 
-fn expandString(input: []const u8, output: &Buffer) %void {
+fn expandString(input: []const u8, output: &Buffer) !void {
     const tokens = try tokenize(input);
     if (tokens.len == 1) {
         return output.resize(0);
@@ -135,7 +132,7 @@ fn expandString(input: []const u8, output: &Buffer) %void {
     }
 }
 
-fn expandNode(node: &const Node, output: &ArrayList(Buffer)) %void {
+fn expandNode(node: &const Node, output: &ArrayList(Buffer)) !void {
     assert(output.len == 0);
     switch (*node) {
         Node.Scalar => |scalar| {
@@ -172,7 +169,7 @@ fn expandNode(node: &const Node, output: &ArrayList(Buffer)) %void {
     }
 }
 
-pub fn main() %void {
+pub fn main() !void {
     var stdin_file = try io.getStdIn();
     var stdout_file = try io.getStdOut();
 
test/standalone/issue_339/build.zig
@@ -1,6 +1,6 @@
 const Builder = @import("std").build.Builder;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     const obj = b.addObject("test", "test.zig");
 
     const test_step = b.step("test", "Test the program");
test/standalone/pkg_import/build.zig
@@ -1,6 +1,6 @@
 const Builder = @import("std").build.Builder;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     const exe = b.addExecutable("test", "test.zig");
     exe.addPackagePath("my_pkg", "pkg.zig");
 
test/standalone/pkg_import/test.zig
@@ -1,6 +1,6 @@
 const my_pkg = @import("my_pkg");
 const assert = @import("std").debug.assert;
 
-pub fn main() %void {
+pub fn main() !void {
     assert(my_pkg.add(10, 20) == 30);
 }
test/standalone/use_alias/build.zig
@@ -1,6 +1,6 @@
 const Builder = @import("std").build.Builder;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     b.addCIncludePath(".");
 
     const main = b.addTest("main.zig");
test/compare_output.zig
@@ -15,7 +15,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
             \\use @import("std").io;
             \\use @import("foo.zig");
             \\
-            \\pub fn main() %void {
+            \\pub fn main() !void {
             \\    privateFunction();
             \\    const stdout = &(FileOutStream.init(&(getStdOut() catch unreachable)).stream);
             \\    stdout.print("OK 2\n") catch unreachable;
@@ -49,7 +49,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
             \\use @import("foo.zig");
             \\use @import("bar.zig");
             \\
-            \\pub fn main() %void {
+            \\pub fn main() !void {
             \\    foo_function();
             \\    bar_function();
             \\}
@@ -89,7 +89,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         var tc = cases.create("two files use import each other",
             \\use @import("a.zig");
             \\
-            \\pub fn main() %void {
+            \\pub fn main() !void {
             \\    ok();
             \\}
         , "OK\n");
@@ -118,7 +118,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
     cases.add("hello world without libc",
         \\const io = @import("std").io;
         \\
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
         \\    stdout.print("Hello, world!\n{d4} {x3} {c}\n", u32(12), u16(0x12), u8('a')) catch unreachable;
         \\}
@@ -268,7 +268,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\const z = io.stdin_fileno;
         \\const x : @typeOf(y) = 1234;
         \\const y : u16 = 5678;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    var x_local : i32 = print_ok(x);
         \\}
         \\fn print_ok(val: @typeOf(x)) @typeOf(foo) {
@@ -351,7 +351,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    fn method(b: &const Bar) bool { return true; }
         \\};
         \\
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const bar = Bar {.field2 = 13,};
         \\    const foo = Foo {.field1 = bar,};
         \\    const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
@@ -367,7 +367,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
 
     cases.add("defer with only fallthrough",
         \\const io = @import("std").io;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
         \\    stdout.print("before\n") catch unreachable;
         \\    defer stdout.print("defer1\n") catch unreachable;
@@ -380,7 +380,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
     cases.add("defer with return",
         \\const io = @import("std").io;
         \\const os = @import("std").os;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
         \\    stdout.print("before\n") catch unreachable;
         \\    defer stdout.print("defer1\n") catch unreachable;
@@ -394,10 +394,10 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
 
     cases.add("errdefer and it fails",
         \\const io = @import("std").io;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    do_test() catch return;
         \\}
-        \\fn do_test() %void {
+        \\fn do_test() !void {
         \\    const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
         \\    stdout.print("before\n") catch unreachable;
         \\    defer stdout.print("defer1\n") catch unreachable;
@@ -407,17 +407,17 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    stdout.print("after\n") catch unreachable;
         \\}
         \\error IToldYouItWouldFail;
-        \\fn its_gonna_fail() %void {
+        \\fn its_gonna_fail() !void {
         \\    return error.IToldYouItWouldFail;
         \\}
     , "before\ndeferErr\ndefer1\n");
 
     cases.add("errdefer and it passes",
         \\const io = @import("std").io;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    do_test() catch return;
         \\}
-        \\fn do_test() %void {
+        \\fn do_test() !void {
         \\    const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
         \\    stdout.print("before\n") catch unreachable;
         \\    defer stdout.print("defer1\n") catch unreachable;
@@ -434,7 +434,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
             \\const foo_txt = @embedFile("foo.txt");
             \\const io = @import("std").io;
             \\
-            \\pub fn main() %void {
+            \\pub fn main() !void {
             \\    const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
             \\    stdout.print(foo_txt) catch unreachable;
             \\}
@@ -452,7 +452,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
             \\const os = std.os;
             \\const allocator = std.debug.global_allocator;
             \\
-            \\pub fn main() %void {
+            \\pub fn main() !void {
             \\    var args_it = os.args();
             \\    var stdout_file = try io.getStdOut();
             \\    var stdout_adapter = io.FileOutStream.init(&stdout_file);
@@ -493,7 +493,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
             \\const os = std.os;
             \\const allocator = std.debug.global_allocator;
             \\
-            \\pub fn main() %void {
+            \\pub fn main() !void {
             \\    var args_it = os.args();
             \\    var stdout_file = try io.getStdOut();
             \\    var stdout_adapter = io.FileOutStream.init(&stdout_file);
test/compile_errors.zig
@@ -1383,7 +1383,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
     , ".tmp_source.zig:6:13: error: cannot assign to constant");
 
     cases.add("return from defer expression",
-        \\pub fn testTrickyDefer() %void {
+        \\pub fn testTrickyDefer() !void {
         \\    defer canFail() catch {};
         \\
         \\    defer try canFail();
@@ -1970,7 +1970,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
         \\fn foo1(args: ...) void {}
         \\fn foo2(args: ...) void {}
         \\
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    foos[0]();
         \\}
     ,
@@ -1982,7 +1982,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
         \\fn foo1(arg: var) void {}
         \\fn foo2(arg: var) void {}
         \\
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    foos[0](true);
         \\}
     ,
test/runtime_safety.zig
@@ -5,7 +5,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
         \\    @import("std").os.exit(126);
         \\}
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    @panic("oh no");
         \\}
     );
@@ -14,7 +14,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
         \\    @import("std").os.exit(126);
         \\}
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const a = []i32{1, 2, 3, 4};
         \\    baz(bar(a));
         \\}
@@ -29,7 +29,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = add(65530, 10);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -43,7 +43,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = sub(10, 20);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -57,7 +57,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = mul(300, 6000);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -71,7 +71,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = neg(-32768);
         \\    if (x == 32767) return error.Whatever;
         \\}
@@ -85,7 +85,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = div(-32768, -1);
         \\    if (x == 32767) return error.Whatever;
         \\}
@@ -99,7 +99,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = shl(-16385, 1);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -113,7 +113,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = shl(0b0010111111111111, 3);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -127,7 +127,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = shr(-16385, 1);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -141,7 +141,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = shr(0b0010111111111111, 3);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -155,7 +155,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = div0(999, 0);
         \\}
         \\fn div0(a: i32, b: i32) i32 {
@@ -168,7 +168,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = divExact(10, 3);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -182,7 +182,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = widenSlice([]u8{1, 2, 3, 4, 5});
         \\    if (x.len == 0) return error.Whatever;
         \\}
@@ -196,7 +196,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = shorten_cast(200);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -210,7 +210,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    const x = unsigned_cast(-10);
         \\    if (x == 0) return error.Whatever;
         \\}
@@ -227,10 +227,10 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(0); // test failed
         \\}
         \\error Whatever;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    bar() catch unreachable;
         \\}
-        \\fn bar() %void {
+        \\fn bar() !void {
         \\    return error.Whatever;
         \\}
     );
@@ -239,7 +239,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
         \\    @import("std").os.exit(126);
         \\}
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    _ = bar(9999);
         \\}
         \\fn bar(x: u32) error {
@@ -252,7 +252,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    @import("std").os.exit(126);
         \\}
         \\error Wrong;
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    var array align(4) = []u32{0x11111111, 0x11111111};
         \\    const bytes = ([]u8)(array[0..]);
         \\    if (foo(bytes) != 0x11111111) return error.Wrong;
@@ -274,7 +274,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
         \\    int: u32,
         \\};
         \\
-        \\pub fn main() %void {
+        \\pub fn main() !void {
         \\    var f = Foo { .int = 42 };
         \\    bar(&f);
         \\}
test/tests.zig
@@ -45,9 +45,6 @@ const test_targets = []TestTarget {
     },
 };
 
-error TestFailed;
-error CompilationIncorrectlySucceeded;
-
 const max_stdout_size = 1 * 1024 * 1024; // 1 MB
 
 pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
@@ -248,7 +245,7 @@ pub const CompareOutputContext = struct {
             return ptr;
         }
 
-        fn make(step: &build.Step) %void {
+        fn make(step: &build.Step) !void {
             const self = @fieldParentPtr(RunCompareOutputStep, "step", step);
             const b = self.context.b;
 
@@ -337,7 +334,7 @@ pub const CompareOutputContext = struct {
             return ptr;
         }
 
-        fn make(step: &build.Step) %void {
+        fn make(step: &build.Step) !void {
             const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step);
             const b = self.context.b;
 
@@ -563,7 +560,7 @@ pub const CompileErrorContext = struct {
             return ptr;
         }
 
-        fn make(step: &build.Step) %void {
+        fn make(step: &build.Step) !void {
             const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
             const b = self.context.b;
 
@@ -847,7 +844,7 @@ pub const TranslateCContext = struct {
             return ptr;
         }
 
-        fn make(step: &build.Step) %void {
+        fn make(step: &build.Step) !void {
             const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);
             const b = self.context.b;
 
@@ -1045,7 +1042,7 @@ pub const GenHContext = struct {
             return ptr;
         }
 
-        fn make(step: &build.Step) %void {
+        fn make(step: &build.Step) !void {
             const self = @fieldParentPtr(GenHCmpOutputStep, "step", step);
             const b = self.context.b;
 
build.zig
@@ -10,7 +10,7 @@ const ArrayList = std.ArrayList;
 const Buffer = std.Buffer;
 const io = std.io;
 
-pub fn build(b: &Builder) %void {
+pub fn build(b: &Builder) !void {
     const mode = b.standardReleaseOptions();
 
     var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
@@ -149,7 +149,7 @@ const LibraryDep = struct {
     includes: ArrayList([]const u8),
 };
 
-fn findLLVM(b: &Builder, llvm_config_exe: []const u8) %LibraryDep {
+fn findLLVM(b: &Builder, llvm_config_exe: []const u8) !LibraryDep {
     const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
     const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"});
     const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"});
TODO
@@ -0,0 +1,5 @@
+sed -i 's/\(\bfn .*) \)%\(.*{\)$/\1!\2/g' $(find .. -name "*.zig")
+
+comptime assert(error{} ! i32 == i32);
+
+