| ... | ... | @@ -1156,10 +1156,8 @@ fn addOne(number: i32) i32 { |
| 1156 | 1156 | {#link|identifier|Identifiers#}, followed by a {#link|block|Blocks#} containing any valid Zig code that |
| 1157 | 1157 | is allowed in a {#link|function|Functions#}. |
| 1158 | 1158 | </p> |
| 1159 | | <aside> |
| 1160 | | By convention, non-named tests should only be used to {#link|make other tests run|Nested Container Tests#}. |
| 1161 | | Non-named tests cannot be {#link|filtered|Skip Tests#}. |
| 1162 | | </aside> |
| 1159 | <p>Non-named test blocks always run during test builds and are exempt from |
| 1160 | {#link|Skip Tests#}.</p> |
| 1163 | 1161 | <p> |
| 1164 | 1162 | Test declarations are similar to {#link|Functions#}: they have a return type and a block of code. The implicit |
| 1165 | 1163 | return type of {#syntax#}test{#endsyntax#} is the {#link|Error Union Type#} {#syntax#}anyerror!void{#endsyntax#}, |
| ... | ... | @@ -5009,12 +5007,12 @@ test "if error union with optional" { |
| 5009 | 5007 | {#see_also|Optionals|Errors#} |
| 5010 | 5008 | {#header_close#} |
| 5011 | 5009 | {#header_open|defer#} |
| 5010 | <p>Executes an expression unconditionally at scope exit.</p> |
| 5012 | 5011 | {#code_begin|test|test_defer#} |
| 5013 | 5012 | const std = @import("std"); |
| 5014 | 5013 | const expect = std.testing.expect; |
| 5015 | 5014 | const print = std.debug.print; |
| 5016 | 5015 | |
| 5017 | | // defer will execute an expression at the end of the current scope. |
| 5018 | 5016 | fn deferExample() !usize { |
| 5019 | 5017 | var a: usize = 1; |
| 5020 | 5018 | |
| ... | ... | @@ -5031,10 +5029,14 @@ fn deferExample() !usize { |
| 5031 | 5029 | test "defer basics" { |
| 5032 | 5030 | try expect((try deferExample()) == 5); |
| 5033 | 5031 | } |
| 5032 | {#code_end#} |
| 5033 | <p>Defer expressions are evaluated in reverse order.</p> |
| 5034 | {#code_begin|test|defer_unwind#} |
| 5035 | const std = @import("std"); |
| 5036 | const expect = std.testing.expect; |
| 5037 | const print = std.debug.print; |
| 5034 | 5038 | |
| 5035 | | // If multiple defer statements are specified, they will be executed in |
| 5036 | | // the reverse order they were run. |
| 5037 | | fn deferUnwindExample() void { |
| 5039 | test "defer unwinding" { |
| 5038 | 5040 | print("\n", .{}); |
| 5039 | 5041 | |
| 5040 | 5042 | defer { |
| ... | ... | @@ -5050,63 +5052,15 @@ fn deferUnwindExample() void { |
| 5050 | 5052 | } |
| 5051 | 5053 | } |
| 5052 | 5054 | } |
| 5053 | | |
| 5054 | | test "defer unwinding" { |
| 5055 | | deferUnwindExample(); |
| 5056 | | } |
| 5057 | 5055 | {#code_end#} |
| 5056 | <p>Inside a defer expression the return statement is not allowed.</p> |
| 5058 | 5057 | {#code_begin|test_err|test_invalid_defer|cannot return from defer expression#} |
| 5059 | | // Inside a defer expression the return statement is not allowed. |
| 5060 | 5058 | fn deferInvalidExample() !void { |
| 5061 | 5059 | defer { |
| 5062 | 5060 | return error.DeferError; |
| 5063 | 5061 | } |
| 5064 | 5062 | |
| 5065 | 5063 | return error.DeferError; |
| 5066 | | } |
| 5067 | | {#code_end#} |
| 5068 | | {#code_begin|test|test_errdefer#} |
| 5069 | | const std = @import("std"); |
| 5070 | | const print = std.debug.print; |
| 5071 | | |
| 5072 | | // The errdefer keyword is similar to defer, but will only execute if the |
| 5073 | | // scope returns with an error. |
| 5074 | | // |
| 5075 | | // This is especially useful in allowing a function to clean up properly |
| 5076 | | // on error, and replaces goto error handling tactics as seen in c. |
| 5077 | | fn deferErrorExample(is_error: bool) !void { |
| 5078 | | print("\nstart of function\n", .{}); |
| 5079 | | |
| 5080 | | // This will always be executed on exit |
| 5081 | | defer { |
| 5082 | | print("end of function\n", .{}); |
| 5083 | | } |
| 5084 | | |
| 5085 | | errdefer { |
| 5086 | | print("encountered an error!\n", .{}); |
| 5087 | | } |
| 5088 | | |
| 5089 | | if (is_error) { |
| 5090 | | return error.DeferError; |
| 5091 | | } |
| 5092 | | } |
| 5093 | | |
| 5094 | | // The errdefer keyword also supports an alternative syntax to capture the |
| 5095 | | // generated error. |
| 5096 | | // |
| 5097 | | // This is useful for printing an additional error message during clean up. |
| 5098 | | fn deferErrorCaptureExample() !void { |
| 5099 | | errdefer |err| { |
| 5100 | | std.debug.print("the error is {s}\n", .{@errorName(err)}); |
| 5101 | | } |
| 5102 | | |
| 5103 | | return error.DeferError; |
| 5104 | | } |
| 5105 | | |
| 5106 | | test "errdefer unwinding" { |
| 5107 | | deferErrorExample(false) catch {}; |
| 5108 | | deferErrorExample(true) catch {}; |
| 5109 | | deferErrorCaptureExample() catch {}; |
| 5110 | 5064 | } |
| 5111 | 5065 | {#code_end#} |
| 5112 | 5066 | {#see_also|Errors#} |