replace %defer with errdefer

See #632

now we have 1 less sigil
This commit is contained in:
Andrew Kelley 2018-01-23 23:08:09 -05:00
parent ad2527d47a
commit b3a6faf13e
21 changed files with 87 additions and 89 deletions

View File

@ -318,7 +318,7 @@ const Action = enum {
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); var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator);
%defer urls.deinit(); errdefer urls.deinit();
var header_stack_size: usize = 0; var header_stack_size: usize = 0;
var last_action = Action.Open; var last_action = Action.Open;
@ -399,7 +399,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc {
} }
} else if (mem.eql(u8, tag_name, "see_also")) { } else if (mem.eql(u8, tag_name, "see_also")) {
var list = std.ArrayList(SeeAlsoItem).init(allocator); var list = std.ArrayList(SeeAlsoItem).init(allocator);
%defer list.deinit(); errdefer list.deinit();
while (true) { while (true) {
const see_also_tok = tokenizer.next(); const see_also_tok = tokenizer.next();

View File

@ -2533,7 +2533,7 @@ test "defer unwinding" {
deferUnwindExample(); deferUnwindExample();
} }
// The %defer keyword is similar to defer, but will only execute if the // The errdefer keyword is similar to defer, but will only execute if the
// scope returns with an error. // scope returns with an error.
// //
// This is especially useful in allowing a function to clean up properly // This is especially useful in allowing a function to clean up properly
@ -2547,7 +2547,7 @@ fn deferErrorExample(is_error: bool) -> %void {
warn("end of function\n"); warn("end of function\n");
} }
%defer { errdefer {
warn("encountered an error!\n"); warn("encountered an error!\n");
} }
@ -2556,7 +2556,7 @@ fn deferErrorExample(is_error: bool) -> %void {
} }
} }
test "%defer unwinding" { test "errdefer unwinding" {
_ = deferErrorExample(false); _ = deferErrorExample(false);
_ = deferErrorExample(true); _ = deferErrorExample(true);
} }
@ -2922,7 +2922,7 @@ fn doAThing(str: []u8) {
{#code_end#} {#code_end#}
<p> <p>
The other component to error handling is defer statements. The other component to error handling is defer statements.
In addition to an unconditional <code>defer</code>, Zig has <code>%defer</code>, In addition to an unconditional <code>defer</code>, Zig has <code>errdefer</code>,
which evaluates the deferred expression on block exit path if and only if which evaluates the deferred expression on block exit path if and only if
the function returned with an error from the block. the function returned with an error from the block.
</p> </p>
@ -2934,7 +2934,7 @@ fn createFoo(param: i32) -> %Foo {
const foo = try tryToAllocateFoo(); const foo = try tryToAllocateFoo();
// now we have allocated foo. we need to free it if the function fails. // now we have allocated foo. we need to free it if the function fails.
// but we want to return it if the function succeeds. // but we want to return it if the function succeeds.
%defer deallocateFoo(foo); errdefer deallocateFoo(foo);
const tmp_buf = allocateTmpBuffer() ?? return error.OutOfMemory; const tmp_buf = allocateTmpBuffer() ?? return error.OutOfMemory;
// tmp_buf is truly a temporary resource, and we for sure want to clean it up // tmp_buf is truly a temporary resource, and we for sure want to clean it up
@ -2943,7 +2943,7 @@ fn createFoo(param: i32) -> %Foo {
if (param > 1337) return error.InvalidParam; if (param > 1337) return error.InvalidParam;
// here the %defer will not run since we're returning success from the function. // here the errdefer will not run since we're returning success from the function.
// but the defer will run! // but the defer will run!
return foo; return foo;
} }
@ -5619,7 +5619,7 @@ TryExpression = "try" Expression
BreakExpression = "break" option(":" Symbol) option(Expression) BreakExpression = "break" option(":" Symbol) option(Expression)
Defer(body) = option("%") "defer" body Defer(body) = ("defer" | "deferror") body
IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body)) IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))

View File

@ -371,7 +371,7 @@ pub fn main2() -> %void {
defer allocator.free(full_cache_dir); defer allocator.free(full_cache_dir);
const zig_lib_dir = try resolveZigLibDir(allocator, zig_install_prefix); const zig_lib_dir = try resolveZigLibDir(allocator, zig_install_prefix);
%defer allocator.free(zig_lib_dir); errdefer allocator.free(zig_lib_dir);
const module = try Module.create(allocator, root_name, zig_root_source_file, const module = try Module.create(allocator, root_name, zig_root_source_file,
Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir); Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir);
@ -587,7 +587,7 @@ fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const
/// Caller must free result /// 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"); const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig");
%defer allocator.free(test_zig_dir); errdefer allocator.free(test_zig_dir);
const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig"); const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig");
defer allocator.free(test_index_file); defer allocator.free(test_index_file);

View File

@ -113,19 +113,19 @@ pub const Module = struct {
kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module
{ {
var name_buffer = try Buffer.init(allocator, name); var name_buffer = try Buffer.init(allocator, name);
%defer name_buffer.deinit(); errdefer name_buffer.deinit();
const context = c.LLVMContextCreate() ?? return error.OutOfMemory; const context = c.LLVMContextCreate() ?? return error.OutOfMemory;
%defer c.LLVMContextDispose(context); errdefer c.LLVMContextDispose(context);
const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory; const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory;
%defer c.LLVMDisposeModule(module); errdefer c.LLVMDisposeModule(module);
const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory; const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory;
%defer c.LLVMDisposeBuilder(builder); errdefer c.LLVMDisposeBuilder(builder);
const module_ptr = try allocator.create(Module); const module_ptr = try allocator.create(Module);
%defer allocator.destroy(module_ptr); errdefer allocator.destroy(module_ptr);
*module_ptr = Module { *module_ptr = Module {
.allocator = allocator, .allocator = allocator,
@ -211,13 +211,13 @@ pub const Module = struct {
try printError("unable to get real path '{}': {}", root_src_path, err); try printError("unable to get real path '{}': {}", root_src_path, err);
return err; return err;
}; };
%defer self.allocator.free(root_src_real_path); errdefer self.allocator.free(root_src_real_path);
const source_code = io.readFileAllocExtra(root_src_real_path, self.allocator, 3) catch |err| { const source_code = io.readFileAllocExtra(root_src_real_path, self.allocator, 3) catch |err| {
try printError("unable to open '{}': {}", root_src_real_path, err); try printError("unable to open '{}': {}", root_src_real_path, err);
return err; return err;
}; };
%defer self.allocator.free(source_code); errdefer self.allocator.free(source_code);
source_code[source_code.len - 3] = '\n'; source_code[source_code.len - 3] = '\n';
source_code[source_code.len - 2] = '\n'; source_code[source_code.len - 2] = '\n';
source_code[source_code.len - 1] = '\n'; source_code[source_code.len - 1] = '\n';

View File

@ -127,7 +127,7 @@ pub const Parser = struct {
const root_node = x: { const root_node = x: {
const root_node = try self.createRoot(); const root_node = try self.createRoot();
%defer self.allocator.destroy(root_node); errdefer self.allocator.destroy(root_node);
// This stack append has to succeed for freeAst to work // This stack append has to succeed for freeAst to work
try stack.append(State.TopLevel); try stack.append(State.TopLevel);
break :x root_node; break :x root_node;
@ -577,7 +577,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); const node = try self.allocator.create(ast.NodeRoot);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeRoot { *node = ast.NodeRoot {
.base = ast.Node {.id = ast.Node.Id.Root}, .base = ast.Node {.id = ast.Node.Id.Root},
@ -590,7 +590,7 @@ pub const Parser = struct {
extern_token: &const ?Token) -> %&ast.NodeVarDecl extern_token: &const ?Token) -> %&ast.NodeVarDecl
{ {
const node = try self.allocator.create(ast.NodeVarDecl); const node = try self.allocator.create(ast.NodeVarDecl);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeVarDecl { *node = ast.NodeVarDecl {
.base = ast.Node {.id = ast.Node.Id.VarDecl}, .base = ast.Node {.id = ast.Node.Id.VarDecl},
@ -613,7 +613,7 @@ pub const Parser = struct {
cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&ast.NodeFnProto cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&ast.NodeFnProto
{ {
const node = try self.allocator.create(ast.NodeFnProto); const node = try self.allocator.create(ast.NodeFnProto);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeFnProto { *node = ast.NodeFnProto {
.base = ast.Node {.id = ast.Node.Id.FnProto}, .base = ast.Node {.id = ast.Node.Id.FnProto},
@ -635,7 +635,7 @@ pub const Parser = struct {
fn createParamDecl(self: &Parser) -> %&ast.NodeParamDecl { fn createParamDecl(self: &Parser) -> %&ast.NodeParamDecl {
const node = try self.allocator.create(ast.NodeParamDecl); const node = try self.allocator.create(ast.NodeParamDecl);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeParamDecl { *node = ast.NodeParamDecl {
.base = ast.Node {.id = ast.Node.Id.ParamDecl}, .base = ast.Node {.id = ast.Node.Id.ParamDecl},
@ -650,7 +650,7 @@ pub const Parser = struct {
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); const node = try self.allocator.create(ast.NodeBlock);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeBlock { *node = ast.NodeBlock {
.base = ast.Node {.id = ast.Node.Id.Block}, .base = ast.Node {.id = ast.Node.Id.Block},
@ -663,7 +663,7 @@ pub const Parser = struct {
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); const node = try self.allocator.create(ast.NodeInfixOp);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeInfixOp { *node = ast.NodeInfixOp {
.base = ast.Node {.id = ast.Node.Id.InfixOp}, .base = ast.Node {.id = ast.Node.Id.InfixOp},
@ -677,7 +677,7 @@ pub const Parser = struct {
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); const node = try self.allocator.create(ast.NodePrefixOp);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodePrefixOp { *node = ast.NodePrefixOp {
.base = ast.Node {.id = ast.Node.Id.PrefixOp}, .base = ast.Node {.id = ast.Node.Id.PrefixOp},
@ -690,7 +690,7 @@ pub const Parser = struct {
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); const node = try self.allocator.create(ast.NodeIdentifier);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeIdentifier { *node = ast.NodeIdentifier {
.base = ast.Node {.id = ast.Node.Id.Identifier}, .base = ast.Node {.id = ast.Node.Id.Identifier},
@ -701,7 +701,7 @@ pub const Parser = struct {
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); const node = try self.allocator.create(ast.NodeIntegerLiteral);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeIntegerLiteral { *node = ast.NodeIntegerLiteral {
.base = ast.Node {.id = ast.Node.Id.IntegerLiteral}, .base = ast.Node {.id = ast.Node.Id.IntegerLiteral},
@ -712,7 +712,7 @@ pub const Parser = struct {
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); const node = try self.allocator.create(ast.NodeFloatLiteral);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
*node = ast.NodeFloatLiteral { *node = ast.NodeFloatLiteral {
.base = ast.Node {.id = ast.Node.Id.FloatLiteral}, .base = ast.Node {.id = ast.Node.Id.FloatLiteral},
@ -723,14 +723,14 @@ pub const Parser = struct {
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); const node = try self.createIdentifier(name_token);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
try dest_ptr.store(&node.base); try dest_ptr.store(&node.base);
return node; 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(); const node = try self.createParamDecl();
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
try list.append(&node.base); try list.append(&node.base);
return node; return node;
} }
@ -740,7 +740,7 @@ pub const Parser = struct {
inline_token: &const ?Token) -> %&ast.NodeFnProto inline_token: &const ?Token) -> %&ast.NodeFnProto
{ {
const node = try self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token); const node = try self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
try list.append(&node.base); try list.append(&node.base);
return node; return node;
} }
@ -749,7 +749,7 @@ pub const Parser = struct {
mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&ast.NodeVarDecl mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&ast.NodeVarDecl
{ {
const node = try self.createVarDecl(visib_token, mut_token, comptime_token, extern_token); const node = try self.createVarDecl(visib_token, mut_token, comptime_token, extern_token);
%defer self.allocator.destroy(node); errdefer self.allocator.destroy(node);
try list.append(&node.base); try list.append(&node.base);
return node; return node;
} }

View File

@ -1495,7 +1495,7 @@ static AstNode *ast_parse_break_expr(ParseContext *pc, size_t *token_index) {
} }
/* /*
Defer(body) = option("%") "defer" body Defer(body) = ("defer" | "errdefer") body
*/ */
static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
Token *token = &pc->tokens->at(*token_index); Token *token = &pc->tokens->at(*token_index);
@ -1503,15 +1503,10 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
NodeType node_type; NodeType node_type;
ReturnKind kind; ReturnKind kind;
if (token->id == TokenIdPercent) { if (token->id == TokenIdKeywordErrdefer) {
Token *next_token = &pc->tokens->at(*token_index + 1); kind = ReturnKindError;
if (next_token->id == TokenIdKeywordDefer) { node_type = NodeTypeDefer;
kind = ReturnKindError; *token_index += 1;
node_type = NodeTypeDefer;
*token_index += 2;
} else {
return nullptr;
}
} else if (token->id == TokenIdKeywordDefer) { } else if (token->id == TokenIdKeywordDefer) {
kind = ReturnKindUnconditional; kind = ReturnKindUnconditional;
node_type = NodeTypeDefer; node_type = NodeTypeDefer;

View File

@ -118,6 +118,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"defer", TokenIdKeywordDefer}, {"defer", TokenIdKeywordDefer},
{"else", TokenIdKeywordElse}, {"else", TokenIdKeywordElse},
{"enum", TokenIdKeywordEnum}, {"enum", TokenIdKeywordEnum},
{"errdefer", TokenIdKeywordErrdefer},
{"error", TokenIdKeywordError}, {"error", TokenIdKeywordError},
{"export", TokenIdKeywordExport}, {"export", TokenIdKeywordExport},
{"extern", TokenIdKeywordExtern}, {"extern", TokenIdKeywordExtern},
@ -1514,6 +1515,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordDefer: return "defer"; case TokenIdKeywordDefer: return "defer";
case TokenIdKeywordElse: return "else"; case TokenIdKeywordElse: return "else";
case TokenIdKeywordEnum: return "enum"; case TokenIdKeywordEnum: return "enum";
case TokenIdKeywordErrdefer: return "errdefer";
case TokenIdKeywordError: return "error"; case TokenIdKeywordError: return "error";
case TokenIdKeywordExport: return "export"; case TokenIdKeywordExport: return "export";
case TokenIdKeywordExtern: return "extern"; case TokenIdKeywordExtern: return "extern";

View File

@ -57,6 +57,7 @@ enum TokenId {
TokenIdKeywordDefer, TokenIdKeywordDefer,
TokenIdKeywordElse, TokenIdKeywordElse,
TokenIdKeywordEnum, TokenIdKeywordEnum,
TokenIdKeywordErrdefer,
TokenIdKeywordError, TokenIdKeywordError,
TokenIdKeywordExport, TokenIdKeywordExport,
TokenIdKeywordExtern, TokenIdKeywordExtern,

View File

@ -30,14 +30,14 @@ pub const BufMap = struct {
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| { if (self.hash_map.get(key)) |entry| {
const value_copy = try self.copy(value); const value_copy = try self.copy(value);
%defer self.free(value_copy); errdefer self.free(value_copy);
_ = try self.hash_map.put(key, value_copy); _ = try self.hash_map.put(key, value_copy);
self.free(entry.value); self.free(entry.value);
} else { } else {
const key_copy = try self.copy(key); const key_copy = try self.copy(key);
%defer self.free(key_copy); errdefer self.free(key_copy);
const value_copy = try self.copy(value); const value_copy = try self.copy(value);
%defer self.free(value_copy); errdefer self.free(value_copy);
_ = try self.hash_map.put(key_copy, value_copy); _ = try self.hash_map.put(key_copy, value_copy);
} }
} }

View File

@ -27,7 +27,7 @@ pub const BufSet = struct {
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) { if (self.hash_map.get(key) == null) {
const key_copy = try self.copy(key); const key_copy = try self.copy(key);
%defer self.free(key_copy); errdefer self.free(key_copy);
_ = try self.hash_map.put(key_copy, {}); _ = try self.hash_map.put(key_copy, {});
} }
} }

View File

@ -71,7 +71,7 @@ pub const NullTerminated2DArray = struct {
byte_count += index_size; byte_count += index_size;
const buf = try allocator.alignedAlloc(u8, @alignOf(?&u8), byte_count); const buf = try allocator.alignedAlloc(u8, @alignOf(?&u8), byte_count);
%defer allocator.free(buf); errdefer allocator.free(buf);
var write_index = index_size; var write_index = index_size;
const index_buf = ([]?&u8)(buf); const index_buf = ([]?&u8)(buf);

View File

@ -248,10 +248,10 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace {
.compile_unit_list = ArrayList(CompileUnit).init(allocator), .compile_unit_list = ArrayList(CompileUnit).init(allocator),
}; };
st.self_exe_file = try os.openSelfExe(); st.self_exe_file = try os.openSelfExe();
%defer st.self_exe_file.close(); errdefer st.self_exe_file.close();
try st.elf.openFile(allocator, &st.self_exe_file); try st.elf.openFile(allocator, &st.self_exe_file);
%defer st.elf.close(); errdefer st.elf.close();
st.debug_info = (try st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo; st.debug_info = (try st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo;
st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo;
@ -524,7 +524,7 @@ const LineNumberProgram = struct {
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
} else self.include_dirs[file_entry.dir_index]; } else self.include_dirs[file_entry.dir_index];
const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
%defer self.file_entries.allocator.free(file_name); errdefer self.file_entries.allocator.free(file_name);
return LineInfo { return LineInfo {
.line = if (self.prev_line >= 0) usize(self.prev_line) else 0, .line = if (self.prev_line >= 0) usize(self.prev_line) else 0,
.column = self.prev_column, .column = self.prev_column,
@ -563,7 +563,7 @@ fn getString(st: &ElfStackTrace, offset: u64) -> %[]u8 {
fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 { fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 {
const buf = try global_allocator.alloc(u8, size); const buf = try global_allocator.alloc(u8, size);
%defer global_allocator.free(buf); errdefer global_allocator.free(buf);
if ((try in_stream.read(buf)) < size) return error.EndOfFile; if ((try in_stream.read(buf)) < size) return error.EndOfFile;
return buf; return buf;
} }

View File

@ -183,7 +183,7 @@ pub const Elf = struct {
try elf.in_file.seekTo(elf.section_header_offset); try elf.in_file.seekTo(elf.section_header_offset);
elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count);
%defer elf.allocator.free(elf.section_headers); errdefer elf.allocator.free(elf.section_headers);
if (elf.is_64) { if (elf.is_64) {
if (sh_entry_size != 64) return error.InvalidFormat; if (sh_entry_size != 64) return error.InvalidFormat;

View File

@ -550,7 +550,7 @@ pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len
const size = try file.getEndPos(); const size = try file.getEndPos();
const buf = try allocator.alloc(u8, size + extra_len); const buf = try allocator.alloc(u8, size + extra_len);
%defer allocator.free(buf); errdefer allocator.free(buf);
var adapter = FileInStream.init(&file); var adapter = FileInStream.init(&file);
try adapter.stream.readNoEof(buf[0..size]); try adapter.stream.readNoEof(buf[0..size]);

View File

@ -440,7 +440,7 @@ pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 {
} }
const buf = try allocator.alloc(u8, total_strings_len); const buf = try allocator.alloc(u8, total_strings_len);
%defer allocator.free(buf); errdefer allocator.free(buf);
var buf_index: usize = 0; var buf_index: usize = 0;
comptime var string_i = 0; comptime var string_i = 0;

View File

@ -76,7 +76,7 @@ pub const ChildProcess = struct {
/// On success must call deinit. /// 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); const child = try allocator.create(ChildProcess);
%defer allocator.destroy(child); errdefer allocator.destroy(child);
*child = ChildProcess { *child = ChildProcess {
.allocator = allocator, .allocator = allocator,
@ -336,13 +336,13 @@ pub const ChildProcess = struct {
install_SIGCHLD_handler(); install_SIGCHLD_handler();
const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined; const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined;
%defer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); }; errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); };
const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined; const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined;
%defer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); }; errdefer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); };
const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined; const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined;
%defer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; errdefer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); };
const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
const dev_null_fd = if (any_ignore) const dev_null_fd = if (any_ignore)
@ -367,7 +367,7 @@ pub const ChildProcess = struct {
// This pipe is used to communicate errors between the time of fork // This pipe is used to communicate errors between the time of fork
// and execve from the child process to the parent process. // and execve from the child process to the parent process.
const err_pipe = try makePipe(); const err_pipe = try makePipe();
%defer destroyPipe(err_pipe); errdefer destroyPipe(err_pipe);
block_SIGCHLD(); block_SIGCHLD();
const pid_result = posix.fork(); const pid_result = posix.fork();
@ -479,7 +479,7 @@ pub const ChildProcess = struct {
g_hChildStd_IN_Rd = null; g_hChildStd_IN_Rd = null;
}, },
} }
%defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); }; errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); };
var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; var g_hChildStd_OUT_Rd: ?windows.HANDLE = null;
var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; var g_hChildStd_OUT_Wr: ?windows.HANDLE = null;
@ -497,7 +497,7 @@ pub const ChildProcess = struct {
g_hChildStd_OUT_Wr = null; g_hChildStd_OUT_Wr = null;
}, },
} }
%defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); };
var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; var g_hChildStd_ERR_Rd: ?windows.HANDLE = null;
var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; var g_hChildStd_ERR_Wr: ?windows.HANDLE = null;
@ -515,7 +515,7 @@ pub const ChildProcess = struct {
g_hChildStd_ERR_Wr = null; g_hChildStd_ERR_Wr = null;
}, },
} }
%defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); };
const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv); const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv);
defer self.allocator.free(cmd_line); defer self.allocator.free(cmd_line);
@ -722,7 +722,7 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S
var rd_h: windows.HANDLE = undefined; var rd_h: windows.HANDLE = undefined;
var wr_h: windows.HANDLE = undefined; var wr_h: windows.HANDLE = undefined;
try windowsMakePipe(&rd_h, &wr_h, sattr); try windowsMakePipe(&rd_h, &wr_h, sattr);
%defer windowsDestroyPipe(rd_h, wr_h); errdefer windowsDestroyPipe(rd_h, wr_h);
try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0); try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0);
*rd = rd_h; *rd = rd_h;
*wr = wr_h; *wr = wr_h;
@ -732,7 +732,7 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const
var rd_h: windows.HANDLE = undefined; var rd_h: windows.HANDLE = undefined;
var wr_h: windows.HANDLE = undefined; var wr_h: windows.HANDLE = undefined;
try windowsMakePipe(&rd_h, &wr_h, sattr); try windowsMakePipe(&rd_h, &wr_h, sattr);
%defer windowsDestroyPipe(rd_h, wr_h); errdefer windowsDestroyPipe(rd_h, wr_h);
try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0); try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0);
*rd = rd_h; *rd = rd_h;
*wr = wr_h; *wr = wr_h;

View File

@ -311,7 +311,7 @@ pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap)
const envp_count = env_map.count(); const envp_count = env_map.count();
const envp_buf = try allocator.alloc(?&u8, envp_count + 1); const envp_buf = try allocator.alloc(?&u8, envp_count + 1);
mem.set(?&u8, envp_buf, null); mem.set(?&u8, envp_buf, null);
%defer freeNullDelimitedEnvMap(allocator, envp_buf); errdefer freeNullDelimitedEnvMap(allocator, envp_buf);
{ {
var it = env_map.iterator(); var it = env_map.iterator();
var i: usize = 0; var i: usize = 0;
@ -421,7 +421,7 @@ pub var posix_environ_raw: []&u8 = undefined;
/// Caller must free result when done. /// Caller must free result when done.
pub fn getEnvMap(allocator: &Allocator) -> %BufMap { pub fn getEnvMap(allocator: &Allocator) -> %BufMap {
var result = BufMap.init(allocator); var result = BufMap.init(allocator);
%defer result.deinit(); errdefer result.deinit();
if (is_windows) { if (is_windows) {
const ptr = windows.GetEnvironmentStringsA() ?? return error.OutOfMemory; const ptr = windows.GetEnvironmentStringsA() ?? return error.OutOfMemory;
@ -489,7 +489,7 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 {
defer allocator.free(key_with_null); defer allocator.free(key_with_null);
var buf = try allocator.alloc(u8, 256); var buf = try allocator.alloc(u8, 256);
%defer allocator.free(buf); errdefer allocator.free(buf);
while (true) { while (true) {
const windows_buf_len = try math.cast(windows.DWORD, buf.len); const windows_buf_len = try math.cast(windows.DWORD, buf.len);
@ -521,7 +521,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 {
switch (builtin.os) { switch (builtin.os) {
Os.windows => { Os.windows => {
var buf = try allocator.alloc(u8, 256); var buf = try allocator.alloc(u8, 256);
%defer allocator.free(buf); errdefer allocator.free(buf);
while (true) { while (true) {
const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr); const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr);
@ -543,7 +543,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 {
}, },
else => { else => {
var buf = try allocator.alloc(u8, 1024); var buf = try allocator.alloc(u8, 1024);
%defer allocator.free(buf); errdefer allocator.free(buf);
while (true) { while (true) {
const err = posix.getErrno(posix.getcwd(buf.ptr, buf.len)); const err = posix.getErrno(posix.getcwd(buf.ptr, buf.len));
if (err == posix.ERANGE) { if (err == posix.ERANGE) {
@ -724,7 +724,7 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [
var out_file = try io.File.openWriteMode(tmp_path, mode, allocator); var out_file = try io.File.openWriteMode(tmp_path, mode, allocator);
defer out_file.close(); defer out_file.close();
%defer _ = deleteFile(allocator, tmp_path); errdefer _ = deleteFile(allocator, tmp_path);
var in_file = try io.File.openRead(source_path, allocator); var in_file = try io.File.openRead(source_path, allocator);
defer in_file.close(); defer in_file.close();
@ -1074,7 +1074,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
path_buf[pathname.len] = 0; path_buf[pathname.len] = 0;
var result_buf = try allocator.alloc(u8, 1024); var result_buf = try allocator.alloc(u8, 1024);
%defer allocator.free(result_buf); errdefer allocator.free(result_buf);
while (true) { while (true) {
const ret_val = posix.readlink(path_buf.ptr, result_buf.ptr, result_buf.len); const ret_val = posix.readlink(path_buf.ptr, result_buf.ptr, result_buf.len);
const err = posix.getErrno(ret_val); const err = posix.getErrno(ret_val);
@ -1443,7 +1443,7 @@ pub fn argsAlloc(allocator: &mem.Allocator) -> %[]const []u8 {
const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len); const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len);
const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len); const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len);
const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);
%defer allocator.free(buf); errdefer allocator.free(buf);
const result_slice_list = ([][]u8)(buf[0..slice_list_bytes]); const result_slice_list = ([][]u8)(buf[0..slice_list_bytes]);
const result_contents = buf[slice_list_bytes..]; const result_contents = buf[slice_list_bytes..];
@ -1556,7 +1556,7 @@ pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 {
}, },
Os.windows => { Os.windows => {
var out_path = try Buffer.initSize(allocator, 0xff); var out_path = try Buffer.initSize(allocator, 0xff);
%defer out_path.deinit(); errdefer out_path.deinit();
while (true) { while (true) {
const dword_len = try math.cast(windows.DWORD, out_path.len()); const dword_len = try math.cast(windows.DWORD, out_path.len());
const copied_amt = windows.GetModuleFileNameA(null, out_path.ptr(), dword_len); const copied_amt = windows.GetModuleFileNameA(null, out_path.ptr(), dword_len);
@ -1579,7 +1579,7 @@ pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 {
const ret1 = c._NSGetExecutablePath(undefined, &u32_len); const ret1 = c._NSGetExecutablePath(undefined, &u32_len);
assert(ret1 != 0); assert(ret1 != 0);
const bytes = try allocator.alloc(u8, u32_len); const bytes = try allocator.alloc(u8, u32_len);
%defer allocator.free(bytes); errdefer allocator.free(bytes);
const ret2 = c._NSGetExecutablePath(bytes.ptr, &u32_len); const ret2 = c._NSGetExecutablePath(bytes.ptr, &u32_len);
assert(ret2 == 0); assert(ret2 == 0);
return bytes; return bytes;
@ -1598,13 +1598,13 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 {
// This path cannot be opened, but it's valid for determining the directory // This path cannot be opened, but it's valid for determining the directory
// the executable was in when it was run. // the executable was in when it was run.
const full_exe_path = try readLink(allocator, "/proc/self/exe"); const full_exe_path = try readLink(allocator, "/proc/self/exe");
%defer allocator.free(full_exe_path); errdefer allocator.free(full_exe_path);
const dir = path.dirname(full_exe_path); const dir = path.dirname(full_exe_path);
return allocator.shrink(u8, full_exe_path, dir.len); return allocator.shrink(u8, full_exe_path, dir.len);
}, },
Os.windows, Os.macosx, Os.ios => { Os.windows, Os.macosx, Os.ios => {
const self_exe_path = try selfExePath(allocator); const self_exe_path = try selfExePath(allocator);
%defer allocator.free(self_exe_path); errdefer allocator.free(self_exe_path);
const dirname = os.path.dirname(self_exe_path); const dirname = os.path.dirname(self_exe_path);
return allocator.shrink(u8, self_exe_path, dirname.len); return allocator.shrink(u8, self_exe_path, dirname.len);
}, },

View File

@ -468,7 +468,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8
} }
have_drive_kind = parsed_cwd.kind; have_drive_kind = parsed_cwd.kind;
} }
%defer allocator.free(result); errdefer allocator.free(result);
// Now we know the disk designator to use, if any, and what kind it is. And our result // Now we know the disk designator to use, if any, and what kind it is. And our result
// is big enough to append all the paths to. // is big enough to append all the paths to.
@ -551,7 +551,7 @@ pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 {
mem.copy(u8, result, cwd); mem.copy(u8, result, cwd);
result_index += cwd.len; result_index += cwd.len;
} }
%defer allocator.free(result); errdefer allocator.free(result);
for (paths[first_index..]) |p, i| { for (paths[first_index..]) |p, i| {
var it = mem.split(p, "/"); var it = mem.split(p, "/");
@ -943,7 +943,7 @@ pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8)
} }
const up_index_end = up_count * "..\\".len; const up_index_end = up_count * "..\\".len;
const result = try allocator.alloc(u8, up_index_end + to_rest.len); const result = try allocator.alloc(u8, up_index_end + to_rest.len);
%defer allocator.free(result); errdefer allocator.free(result);
var result_index: usize = 0; var result_index: usize = 0;
while (result_index < up_index_end) { while (result_index < up_index_end) {
@ -993,7 +993,7 @@ pub fn relativePosix(allocator: &Allocator, from: []const u8, to: []const u8) ->
} }
const up_index_end = up_count * "../".len; const up_index_end = up_count * "../".len;
const result = try allocator.alloc(u8, up_index_end + to_rest.len); const result = try allocator.alloc(u8, up_index_end + to_rest.len);
%defer allocator.free(result); errdefer allocator.free(result);
var result_index: usize = 0; var result_index: usize = 0;
while (result_index < up_index_end) { while (result_index < up_index_end) {
@ -1100,7 +1100,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
} }
defer os.close(h_file); defer os.close(h_file);
var buf = try allocator.alloc(u8, 256); var buf = try allocator.alloc(u8, 256);
%defer allocator.free(buf); errdefer allocator.free(buf);
while (true) { while (true) {
const buf_len = math.cast(windows.DWORD, buf.len) catch return error.NameTooLong; const buf_len = math.cast(windows.DWORD, buf.len) catch return error.NameTooLong;
const result = windows.GetFinalPathNameByHandleA(h_file, buf.ptr, buf_len, windows.VOLUME_NAME_DOS); const result = windows.GetFinalPathNameByHandleA(h_file, buf.ptr, buf_len, windows.VOLUME_NAME_DOS);
@ -1144,7 +1144,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
defer allocator.free(pathname_buf); defer allocator.free(pathname_buf);
const result_buf = try allocator.alloc(u8, posix.PATH_MAX); const result_buf = try allocator.alloc(u8, posix.PATH_MAX);
%defer allocator.free(result_buf); errdefer allocator.free(result_buf);
mem.copy(u8, pathname_buf, pathname); mem.copy(u8, pathname_buf, pathname);
pathname_buf[pathname.len] = 0; pathname_buf[pathname.len] = 0;

View File

@ -133,7 +133,7 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap)
break :x bytes_needed; break :x bytes_needed;
}; };
const result = try allocator.alloc(u8, bytes_needed); const result = try allocator.alloc(u8, bytes_needed);
%defer allocator.free(result); errdefer allocator.free(result);
var it = env_map.iterator(); var it = env_map.iterator();
var i: usize = 0; var i: usize = 0;

View File

@ -8,7 +8,7 @@ error FalseNotAllowed;
fn runSomeErrorDefers(x: bool) -> %bool { fn runSomeErrorDefers(x: bool) -> %bool {
index = 0; index = 0;
defer {result[index] = 'a'; index += 1;} defer {result[index] = 'a'; index += 1;}
%defer {result[index] = 'b'; index += 1;} errdefer {result[index] = 'b'; index += 1;}
defer {result[index] = 'c'; index += 1;} defer {result[index] = 'c'; index += 1;}
return if (x) x else error.FalseNotAllowed; return if (x) x else error.FalseNotAllowed;
} }

View File

@ -392,7 +392,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
\\} \\}
, "before\ndefer2\ndefer1\n"); , "before\ndefer2\ndefer1\n");
cases.add("%defer and it fails", cases.add("errdefer and it fails",
\\const io = @import("std").io; \\const io = @import("std").io;
\\pub fn main() -> %void { \\pub fn main() -> %void {
\\ do_test() catch return; \\ do_test() catch return;
@ -401,7 +401,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
\\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
\\ stdout.print("before\n") catch unreachable; \\ stdout.print("before\n") catch unreachable;
\\ defer stdout.print("defer1\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable;
\\ %defer stdout.print("deferErr\n") catch unreachable; \\ errdefer stdout.print("deferErr\n") catch unreachable;
\\ try its_gonna_fail(); \\ try its_gonna_fail();
\\ defer stdout.print("defer3\n") catch unreachable; \\ defer stdout.print("defer3\n") catch unreachable;
\\ stdout.print("after\n") catch unreachable; \\ stdout.print("after\n") catch unreachable;
@ -412,7 +412,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
\\} \\}
, "before\ndeferErr\ndefer1\n"); , "before\ndeferErr\ndefer1\n");
cases.add("%defer and it passes", cases.add("errdefer and it passes",
\\const io = @import("std").io; \\const io = @import("std").io;
\\pub fn main() -> %void { \\pub fn main() -> %void {
\\ do_test() catch return; \\ do_test() catch return;
@ -421,7 +421,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
\\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream);
\\ stdout.print("before\n") catch unreachable; \\ stdout.print("before\n") catch unreachable;
\\ defer stdout.print("defer1\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable;
\\ %defer stdout.print("deferErr\n") catch unreachable; \\ errdefer stdout.print("deferErr\n") catch unreachable;
\\ try its_gonna_pass(); \\ try its_gonna_pass();
\\ defer stdout.print("defer3\n") catch unreachable; \\ defer stdout.print("defer3\n") catch unreachable;
\\ stdout.print("after\n") catch unreachable; \\ stdout.print("after\n") catch unreachable;