authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-08 03:02:41-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-08 03:02:41-05:00
log76239f2089bfb03b24dac0dcad21c9c430ad076d
tree6cb4afeeccdcac9f4ea1cf2f6d2a823aa107c8ad
parent0d5ff6f4622a492dddbb1fc2b19b3157237500b1

error sets - update langref. all tests passing


2 files changed, 49 insertions(+), 82 deletions(-)

doc/langref.html.in+43-60
......@@ -108,7 +108,7 @@
108108 {#code_begin|exe|hello#}
109109const std = @import("std");
110110
111pub fn main() %void {
111pub fn main() !void {
112112 // If this program is run without stdout attached, exit with an error.
113113 var stdout_file = try std.io.getStdOut();
114114 // If this program encounters pipe failure when printing to stdout, exit
......@@ -129,8 +129,8 @@ pub fn main() void {
129129}
130130 {#code_end#}
131131 <p>
132 Note that we also left off the <code class="zig">%</code> from the return type.
133 In Zig, if your main function cannot fail, you may use the <code class="zig">void</code> return type.
132 Note that we also left off the <code class="zig">!</code> from the return type.
133 In Zig, if your main function cannot fail, you must use the <code class="zig">void</code> return type.
134134 </p>
135135 {#see_also|Values|@import|Errors|Root Source File#}
136136 {#header_close#}
......@@ -151,10 +151,7 @@ const warn = std.debug.warn;
151151const os = std.os;
152152const assert = std.debug.assert;
153153
154// error declaration, makes `error.ArgNotFound` available
155error ArgNotFound;
156
157pub fn main() %void {
154pub fn main() void {
158155 // integers
159156 const one_plus_one: i32 = 1 + 1;
160157 warn("1 + 1 = {}\n", one_plus_one);
......@@ -183,7 +180,7 @@ pub fn main() %void {
183180 @typeName(@typeOf(nullable_value)), nullable_value);
184181
185182 // error union
186 var number_or_error: %i32 = error.ArgNotFound;
183 var number_or_error: error!i32 = error.ArgNotFound;
187184
188185 warn("\nerror union 1\ntype: {}\nvalue: {}\n",
189186 @typeName(@typeOf(number_or_error)), number_or_error);
......@@ -691,7 +688,7 @@ const warn = @import("std").debug.warn;
691688extern fn foo_strict(x: f64) f64;
692689extern fn foo_optimized(x: f64) f64;
693690
694pub fn main() %void {
691pub fn main() void {
695692 const x = 0.001;
696693 warn("optimized = {}\n", foo_optimized(x));
697694 warn("strict = {}\n", foo_strict(x));
......@@ -1046,7 +1043,7 @@ a catch |err| b</code></pre></td>
10461043 <code>err</code> is the <code>error</code> and is in scope of the expression <code>b</code>.
10471044 </td>
10481045 <td>
1049 <pre><code class="zig">const value: %u32 = null;
1046 <pre><code class="zig">const value: error!u32 = error.Broken;
10501047const unwrapped = value catch 1234;
10511048unwrapped == 1234</code></pre>
10521049 </td>
......@@ -1279,7 +1276,8 @@ const ptr = &amp;x;
12791276 {#header_close#}
12801277 {#header_open|Precedence#}
12811278 <pre><code>x() x[] x.y
1282!x -x -%x ~x *x &amp;x ?x %x ??x
1279a!b
1280!x -x -%x ~x *x &amp;x ?x ??x
12831281x{}
12841282! * / % ** *%
12851283+ - ++ +% -%
......@@ -2278,8 +2276,8 @@ fn eventuallyNullSequence() ?u32 {
22782276 break :blk numbers_left;
22792277 };
22802278}
2281error ReachedZero;
2282fn eventuallyErrorSequence() %u32 {
2279
2280fn eventuallyErrorSequence() error!u32 {
22832281 return if (numbers_left == 0) error.ReachedZero else blk: {
22842282 numbers_left -= 1;
22852283 break :blk numbers_left;
......@@ -2408,7 +2406,7 @@ fn typeNameLength(comptime T: type) usize {
24082406// If expressions have three uses, corresponding to the three types:
24092407// * bool
24102408// * ?T
2411// * %T
2409// * error!T
24122410
24132411const assert = @import("std").debug.assert;
24142412
......@@ -2469,20 +2467,18 @@ test "if nullable" {
24692467 }
24702468}
24712469
2472error BadValue;
2473error LessBadValue;
24742470test "if error union" {
24752471 // If expressions test for errors.
24762472 // Note the |err| capture on the else.
24772473
2478 const a: %u32 = 0;
2474 const a: error!u32 = 0;
24792475 if (a) |value| {
24802476 assert(value == 0);
24812477 } else |err| {
24822478 unreachable;
24832479 }
24842480
2485 const b: %u32 = error.BadValue;
2481 const b: error!u32 = error.BadValue;
24862482 if (b) |value| {
24872483 unreachable;
24882484 } else |err| {
......@@ -2500,7 +2496,7 @@ test "if error union" {
25002496 }
25012497
25022498 // Access the value by reference using a pointer capture.
2503 var c: %u32 = 3;
2499 var c: error!u32 = 3;
25042500 if (c) |*value| {
25052501 *value = 9;
25062502 } else |err| {
......@@ -2568,8 +2564,7 @@ test "defer unwinding" {
25682564//
25692565// This is especially useful in allowing a function to clean up properly
25702566// on error, and replaces goto error handling tactics as seen in c.
2571error DeferError;
2572fn deferErrorExample(is_error: bool) %void {
2567fn deferErrorExample(is_error: bool) !void {
25732568 warn("\nstart of function\n");
25742569
25752570 // This will always be executed on exit
......@@ -2678,7 +2673,7 @@ test "foo" {
26782673 assert(value == 1234);
26792674}
26802675
2681fn bar() %u32 {
2676fn bar() error!u32 {
26822677 return 1234;
26832678}
26842679
......@@ -2791,13 +2786,8 @@ test "implicitly cast to const pointer" {
27912786 One of the distinguishing features of Zig is its exception handling strategy.
27922787 </p>
27932788 <p>
2794 Among the top level declarations available is the error value declaration:
2789 TODO rewrite the errors section to take into account error sets
27952790 </p>
2796 {#code_begin|syntax#}
2797error FileNotFound;
2798error OutOfMemory;
2799error UnexpectedToken;
2800 {#code_end#}
28012791 <p>
28022792 These error values are assigned an unsigned integer value greater than 0 at
28032793 compile time. You are allowed to declare the same error value more than once,
......@@ -2809,26 +2799,23 @@ error UnexpectedToken;
28092799 </p>
28102800 <p>
28112801 Each error value across the entire compilation unit gets a unique integer,
2812 and this determines the size of the pure error type.
2802 and this determines the size of the error set type.
28132803 </p>
28142804 <p>
2815 The pure error type is one of the error values, and in the same way that pointers
2816 cannot be null, a pure error is always an error.
2805 The error set type is one of the error values, and in the same way that pointers
2806 cannot be null, a error set instance is always an error.
28172807 </p>
28182808 {#code_begin|syntax#}const pure_error = error.FileNotFound;{#code_end#}
28192809 <p>
2820 Most of the time you will not find yourself using a pure error type. Instead,
2821 likely you will be using the error union type. This is when you take a normal type,
2822 and prefix it with the <code>%</code> operator.
2810 Most of the time you will not find yourself using an error set type. Instead,
2811 likely you will be using the error union type. This is when you take an error set
2812 and a normal type, and create an error union with the <code>!</code> binary operator.
28232813 </p>
28242814 <p>
28252815 Here is a function to parse a string into a 64-bit integer:
28262816 </p>
28272817 {#code_begin|test#}
2828error InvalidChar;
2829error Overflow;
2830
2831pub fn parseU64(buf: []const u8, radix: u8) %u64 {
2818pub fn parseU64(buf: []const u8, radix: u8) !u64 {
28322819 var x: u64 = 0;
28332820
28342821 for (buf) |c| {
......@@ -2867,13 +2854,14 @@ test "parse u64" {
28672854}
28682855 {#code_end#}
28692856 <p>
2870 Notice the return type is <code>%u64</code>. This means that the function
2871 either returns an unsigned 64 bit integer, or an error.
2857 Notice the return type is <code>!u64</code>. This means that the function
2858 either returns an unsigned 64 bit integer, or an error. We left off the error set
2859 to the left of the <code>!</code>, so the error set is inferred.
28722860 </p>
28732861 <p>
28742862 Within the function definition, you can see some return statements that return
2875 a pure error, and at the bottom a return statement that returns a <code>u64</code>.
2876 Both types implicitly cast to <code>%u64</code>.
2863 an error, and at the bottom a return statement that returns a <code>u64</code>.
2864 Both types implicitly cast to <code>error!u64</code>.
28772865 </p>
28782866 <p>
28792867 What it looks like to use this function varies depending on what you're
......@@ -2900,7 +2888,7 @@ fn doAThing(str: []u8) void {
29002888 <p>Let's say you wanted to return the error if you got one, otherwise continue with the
29012889 function logic:</p>
29022890 {#code_begin|syntax#}
2903fn doAThing(str: []u8) %void {
2891fn doAThing(str: []u8) !void {
29042892 const number = parseU64(str, 10) catch |err| return err;
29052893 // ...
29062894}
......@@ -2909,7 +2897,7 @@ fn doAThing(str: []u8) %void {
29092897 There is a shortcut for this. The <code>try</code> expression:
29102898 </p>
29112899 {#code_begin|syntax#}
2912fn doAThing(str: []u8) %void {
2900fn doAThing(str: []u8) !void {
29132901 const number = try parseU64(str, 10);
29142902 // ...
29152903}
......@@ -2959,7 +2947,7 @@ fn doAThing(str: []u8) void {
29592947 Example:
29602948 </p>
29612949 {#code_begin|syntax#}
2962fn createFoo(param: i32) %Foo {
2950fn createFoo(param: i32) !Foo {
29632951 const foo = try tryToAllocateFoo();
29642952 // now we have allocated foo. we need to free it if the function fails.
29652953 // but we want to return it if the function succeeds.
......@@ -3567,7 +3555,7 @@ pub fn main() void {
35673555
35683556 {#code_begin|syntax#}
35693557/// Calls print and then flushes the buffer.
3570pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) %void {
3558pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) error!void {
35713559 const State = enum {
35723560 Start,
35733561 OpenBrace,
......@@ -3639,7 +3627,7 @@ pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) %void {
36393627 and emits a function that actually looks like this:
36403628 </p>
36413629 {#code_begin|syntax#}
3642pub fn printf(self: &OutStream, arg0: i32, arg1: []const u8) %void {
3630pub fn printf(self: &OutStream, arg0: i32, arg1: []const u8) !void {
36433631 try self.write("here is a string: '");
36443632 try self.printValue(arg0);
36453633 try self.write("' here is a number: ");
......@@ -3653,7 +3641,7 @@ pub fn printf(self: &OutStream, arg0: i32, arg1: []const u8) %void {
36533641 on the type:
36543642 </p>
36553643 {#code_begin|syntax#}
3656pub fn printValue(self: &OutStream, value: var) %void {
3644pub fn printValue(self: &OutStream, value: var) !void {
36573645 const T = @typeOf(value);
36583646 if (@isInteger(T)) {
36593647 return self.printInt(T, value);
......@@ -4582,7 +4570,7 @@ pub const TypeId = enum {
45824570 {#code_begin|syntax#}
45834571const Builder = @import("std").build.Builder;
45844572
4585pub fn build(b: &Builder) %void {
4573pub fn build(b: &Builder) void {
45864574 const exe = b.addExecutable("example", "example.zig");
45874575 exe.setBuildMode(b.standardReleaseOptions());
45884576 b.default_step.dependOn(&exe.step);
......@@ -4724,7 +4712,7 @@ comptime {
47244712 {#code_begin|exe_err#}
47254713const math = @import("std").math;
47264714const warn = @import("std").debug.warn;
4727pub fn main() %void {
4715pub fn main() !void {
47284716 var byte: u8 = 255;
47294717
47304718 byte = if (math.add(u8, byte, 1)) |result| result else |err| {
......@@ -4752,7 +4740,7 @@ pub fn main() %void {
47524740 </p>
47534741 {#code_begin|exe#}
47544742const warn = @import("std").debug.warn;
4755pub fn main() %void {
4743pub fn main() void {
47564744 var byte: u8 = 255;
47574745
47584746 var result: u8 = undefined;
......@@ -4861,14 +4849,12 @@ pub fn main() void {
48614849 {#header_close#}
48624850 {#header_open|Attempt to Unwrap Error#}
48634851 <p>At compile-time:</p>
4864 {#code_begin|test_err|unable to unwrap error 'UnableToReturnNumber'#}
4852 {#code_begin|test_err|caught unexpected error 'UnableToReturnNumber'#}
48654853comptime {
48664854 const number = getNumberOrFail() catch unreachable;
48674855}
48684856
4869error UnableToReturnNumber;
4870
4871fn getNumberOrFail() %i32 {
4857fn getNumberOrFail() !i32 {
48724858 return error.UnableToReturnNumber;
48734859}
48744860 {#code_end#}
......@@ -4888,9 +4874,7 @@ pub fn main() void {
48884874 }
48894875}
48904876
4891error UnableToReturnNumber;
4892
4893fn getNumberOrFail() %i32 {
4877fn getNumberOrFail() !i32 {
48944878 return error.UnableToReturnNumber;
48954879}
48964880 {#code_end#}
......@@ -4898,7 +4882,6 @@ fn getNumberOrFail() %i32 {
48984882 {#header_open|Invalid Error Code#}
48994883 <p>At compile-time:</p>
49004884 {#code_begin|test_err|integer value 11 represents no error#}
4901error AnError;
49024885comptime {
49034886 const err = error.AnError;
49044887 const number = u32(err) + 10;
......@@ -5298,7 +5281,7 @@ int main(int argc, char **argv) {
52985281 {#code_begin|syntax#}
52995282const Builder = @import("std").build.Builder;
53005283
5301pub fn build(b: &Builder) %void {
5284pub fn build(b: &Builder) void {
53025285 const obj = b.addObject("base64", "base64.zig");
53035286
53045287 const exe = b.addCExecutable("test");
test/runtime_safety.zig+6-22
......@@ -5,7 +5,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
55 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
66 \\ @import("std").os.exit(126);
77 \\}
8 \\pub fn main() !void {
8 \\pub fn main() void {
99 \\ @panic("oh no");
1010 \\}
1111 );
......@@ -14,7 +14,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
1414 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
1515 \\ @import("std").os.exit(126);
1616 \\}
17 \\pub fn main() !void {
17 \\pub fn main() void {
1818 \\ const a = []i32{1, 2, 3, 4};
1919 \\ baz(bar(a));
2020 \\}
......@@ -28,7 +28,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
2828 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
2929 \\ @import("std").os.exit(126);
3030 \\}
31 \\error Whatever;
3231 \\pub fn main() !void {
3332 \\ const x = add(65530, 10);
3433 \\ if (x == 0) return error.Whatever;
......@@ -42,7 +41,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
4241 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
4342 \\ @import("std").os.exit(126);
4443 \\}
45 \\error Whatever;
4644 \\pub fn main() !void {
4745 \\ const x = sub(10, 20);
4846 \\ if (x == 0) return error.Whatever;
......@@ -56,7 +54,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
5654 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
5755 \\ @import("std").os.exit(126);
5856 \\}
59 \\error Whatever;
6057 \\pub fn main() !void {
6158 \\ const x = mul(300, 6000);
6259 \\ if (x == 0) return error.Whatever;
......@@ -70,7 +67,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
7067 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
7168 \\ @import("std").os.exit(126);
7269 \\}
73 \\error Whatever;
7470 \\pub fn main() !void {
7571 \\ const x = neg(-32768);
7672 \\ if (x == 32767) return error.Whatever;
......@@ -84,7 +80,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
8480 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
8581 \\ @import("std").os.exit(126);
8682 \\}
87 \\error Whatever;
8883 \\pub fn main() !void {
8984 \\ const x = div(-32768, -1);
9085 \\ if (x == 32767) return error.Whatever;
......@@ -98,7 +93,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
9893 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
9994 \\ @import("std").os.exit(126);
10095 \\}
101 \\error Whatever;
10296 \\pub fn main() !void {
10397 \\ const x = shl(-16385, 1);
10498 \\ if (x == 0) return error.Whatever;
......@@ -112,7 +106,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
112106 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
113107 \\ @import("std").os.exit(126);
114108 \\}
115 \\error Whatever;
116109 \\pub fn main() !void {
117110 \\ const x = shl(0b0010111111111111, 3);
118111 \\ if (x == 0) return error.Whatever;
......@@ -126,7 +119,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
126119 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
127120 \\ @import("std").os.exit(126);
128121 \\}
129 \\error Whatever;
130122 \\pub fn main() !void {
131123 \\ const x = shr(-16385, 1);
132124 \\ if (x == 0) return error.Whatever;
......@@ -140,7 +132,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
140132 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
141133 \\ @import("std").os.exit(126);
142134 \\}
143 \\error Whatever;
144135 \\pub fn main() !void {
145136 \\ const x = shr(0b0010111111111111, 3);
146137 \\ if (x == 0) return error.Whatever;
......@@ -154,8 +145,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
154145 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
155146 \\ @import("std").os.exit(126);
156147 \\}
157 \\error Whatever;
158 \\pub fn main() !void {
148 \\pub fn main() void {
159149 \\ const x = div0(999, 0);
160150 \\}
161151 \\fn div0(a: i32, b: i32) i32 {
......@@ -167,7 +157,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
167157 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
168158 \\ @import("std").os.exit(126);
169159 \\}
170 \\error Whatever;
171160 \\pub fn main() !void {
172161 \\ const x = divExact(10, 3);
173162 \\ if (x == 0) return error.Whatever;
......@@ -181,7 +170,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
181170 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
182171 \\ @import("std").os.exit(126);
183172 \\}
184 \\error Whatever;
185173 \\pub fn main() !void {
186174 \\ const x = widenSlice([]u8{1, 2, 3, 4, 5});
187175 \\ if (x.len == 0) return error.Whatever;
......@@ -195,7 +183,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
195183 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
196184 \\ @import("std").os.exit(126);
197185 \\}
198 \\error Whatever;
199186 \\pub fn main() !void {
200187 \\ const x = shorten_cast(200);
201188 \\ if (x == 0) return error.Whatever;
......@@ -209,7 +196,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
209196 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
210197 \\ @import("std").os.exit(126);
211198 \\}
212 \\error Whatever;
213199 \\pub fn main() !void {
214200 \\ const x = unsigned_cast(-10);
215201 \\ if (x == 0) return error.Whatever;
......@@ -226,8 +212,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
226212 \\ }
227213 \\ @import("std").os.exit(0); // test failed
228214 \\}
229 \\error Whatever;
230 \\pub fn main() !void {
215 \\pub fn main() void {
231216 \\ bar() catch unreachable;
232217 \\}
233218 \\fn bar() !void {
......@@ -239,7 +224,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
239224 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
240225 \\ @import("std").os.exit(126);
241226 \\}
242 \\pub fn main() !void {
227 \\pub fn main() void {
243228 \\ _ = bar(9999);
244229 \\}
245230 \\fn bar(x: u32) error {
......@@ -251,7 +236,6 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
251236 \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn {
252237 \\ @import("std").os.exit(126);
253238 \\}
254 \\error Wrong;
255239 \\pub fn main() !void {
256240 \\ var array align(4) = []u32{0x11111111, 0x11111111};
257241 \\ const bytes = ([]u8)(array[0..]);
......@@ -274,7 +258,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
274258 \\ int: u32,
275259 \\};
276260 \\
277 \\pub fn main() !void {
261 \\pub fn main() void {
278262 \\ var f = Foo { .int = 42 };
279263 \\ bar(&f);
280264 \\}