| ... | @@ -1156,10 +1156,8 @@ fn addOne(number: i32) i32 { | ... | @@ -1156,10 +1156,8 @@ fn addOne(number: i32) i32 { |
| 1156 | {#link|identifier|Identifiers#}, followed by a {#link|block|Blocks#} containing any valid Zig code that | 1156 | {#link|identifier|Identifiers#}, followed by a {#link|block|Blocks#} containing any valid Zig code that |
| 1157 | is allowed in a {#link|function|Functions#}. | 1157 | is allowed in a {#link|function|Functions#}. |
| 1158 | </p> | 1158 | </p> |
| 1159 | <aside> | 1159 | <p>Non-named test blocks always run during test builds and are exempt from |
| 1160 | By convention, non-named tests should only be used to {#link|make other tests run|Nested Container Tests#}. | 1160 | {#link|Skip Tests#}.</p> |
| 1161 | Non-named tests cannot be {#link|filtered|Skip Tests#}. | | |
| 1162 | </aside> | | |
| 1163 | <p> | 1161 | <p> |
| 1164 | Test declarations are similar to {#link|Functions#}: they have a return type and a block of code. The implicit | 1162 | Test declarations are similar to {#link|Functions#}: they have a return type and a block of code. The implicit |
| 1165 | return type of {#syntax#}test{#endsyntax#} is the {#link|Error Union Type#} {#syntax#}anyerror!void{#endsyntax#}, | 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,12 +5007,12 @@ test "if error union with optional" { |
| 5009 | {#see_also|Optionals|Errors#} | 5007 | {#see_also|Optionals|Errors#} |
| 5010 | {#header_close#} | 5008 | {#header_close#} |
| 5011 | {#header_open|defer#} | 5009 | {#header_open|defer#} |
| | 5010 | <p>Executes an expression unconditionally at scope exit.</p> |
| 5012 | {#code_begin|test|test_defer#} | 5011 | {#code_begin|test|test_defer#} |
| 5013 | const std = @import("std"); | 5012 | const std = @import("std"); |
| 5014 | const expect = std.testing.expect; | 5013 | const expect = std.testing.expect; |
| 5015 | const print = std.debug.print; | 5014 | const print = std.debug.print; |
| 5016 | | 5015 | |
| 5017 | // defer will execute an expression at the end of the current scope. | | |
| 5018 | fn deferExample() !usize { | 5016 | fn deferExample() !usize { |
| 5019 | var a: usize = 1; | 5017 | var a: usize = 1; |
| 5020 | | 5018 | |
| ... | @@ -5031,10 +5029,14 @@ fn deferExample() !usize { | ... | @@ -5031,10 +5029,14 @@ fn deferExample() !usize { |
| 5031 | test "defer basics" { | 5029 | test "defer basics" { |
| 5032 | try expect((try deferExample()) == 5); | 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 | 5039 | test "defer unwinding" { |
| 5036 | // the reverse order they were run. | | |
| 5037 | fn deferUnwindExample() void { | | |
| 5038 | print("\n", .{}); | 5040 | print("\n", .{}); |
| 5039 | | 5041 | |
| 5040 | defer { | 5042 | defer { |
| ... | @@ -5050,63 +5052,15 @@ fn deferUnwindExample() void { | ... | @@ -5050,63 +5052,15 @@ fn deferUnwindExample() void { |
| 5050 | } | 5052 | } |
| 5051 | } | 5053 | } |
| 5052 | } | 5054 | } |
| 5053 | | | |
| 5054 | test "defer unwinding" { | | |
| 5055 | deferUnwindExample(); | | |
| 5056 | } | | |
| 5057 | {#code_end#} | 5055 | {#code_end#} |
| | 5056 | <p>Inside a defer expression the return statement is not allowed.</p> |
| 5058 | {#code_begin|test_err|test_invalid_defer|cannot return from defer expression#} | 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 | fn deferInvalidExample() !void { | 5058 | fn deferInvalidExample() !void { |
| 5061 | defer { | 5059 | defer { |
| 5062 | return error.DeferError; | 5060 | return error.DeferError; |
| 5063 | } | 5061 | } |
| 5064 | | 5062 | |
| 5065 | return error.DeferError; | 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 | {#code_end#} | 5065 | {#code_end#} |
| 5112 | {#see_also|Errors#} | 5066 | {#see_also|Errors#} |