Skip to content

Commit 8db7a14

Browse files
committed
update errors section of docs
closes #768
1 parent b66547e commit 8db7a14

File tree

1 file changed

+84
-15
lines changed

1 file changed

+84
-15
lines changed

doc/langref.html.in

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,30 +2782,96 @@ test "fn reflection" {
27822782
{#header_close#}
27832783
{#header_close#}
27842784
{#header_open|Errors#}
2785+
{#header_open|Error Set Type#}
27852786
<p>
2786-
One of the distinguishing features of Zig is its exception handling strategy.
2787+
An error set is like an {#link|enum#}.
2788+
However, each error name across the entire compilation gets assigned an unsigned integer
2789+
greater than 0. You are allowed to declare the same error name more than once, and if you do, it
2790+
gets assigned the same integer value.
27872791
</p>
27882792
<p>
2789-
TODO rewrite the errors section to take into account error sets
2793+
The number of unique error values across the entire compilation should determine the size of the error set type.
2794+
However right now it is hard coded to be a <code>u16</code>. See <a href="https://github.com/zig-lang/zig/issues/786">#768</a>.
27902795
</p>
27912796
<p>
2792-
These error values are assigned an unsigned integer value greater than 0 at
2793-
compile time. You are allowed to declare the same error value more than once,
2794-
and if you do, it gets assigned the same integer value.
2797+
You can implicitly cast an error from a subset to its superset:
27952798
</p>
2799+
{#code_begin|test#}
2800+
const std = @import("std");
2801+
2802+
const FileOpenError = error {
2803+
AccessDenied,
2804+
OutOfMemory,
2805+
FileNotFound,
2806+
};
2807+
2808+
const AllocationError = error {
2809+
OutOfMemory,
2810+
};
2811+
2812+
test "implicit cast subset to superset" {
2813+
const err = foo(AllocationError.OutOfMemory);
2814+
std.debug.assert(err == FileOpenError.OutOfMemory);
2815+
}
2816+
2817+
fn foo(err: AllocationError) FileOpenError {
2818+
return err;
2819+
}
2820+
{#code_end#}
27962821
<p>
2797-
You can refer to these error values with the error namespace such as
2798-
<code>error.FileNotFound</code>.
2822+
But you cannot implicitly cast an error from a superset to a subset:
2823+
</p>
2824+
{#code_begin|test_err|not a member of destination error set#}
2825+
const FileOpenError = error {
2826+
AccessDenied,
2827+
OutOfMemory,
2828+
FileNotFound,
2829+
};
2830+
2831+
const AllocationError = error {
2832+
OutOfMemory,
2833+
};
2834+
2835+
test "implicit cast superset to subset" {
2836+
foo(FileOpenError.OutOfMemory) catch {};
2837+
}
2838+
2839+
fn foo(err: FileOpenError) AllocationError {
2840+
return err;
2841+
}
2842+
{#code_end#}
2843+
<p>
2844+
There is a shortcut for declaring an error set with only 1 value, and then getting that value:
2845+
</p>
2846+
{#code_begin|syntax#}
2847+
const err = error.FileNotFound;
2848+
{#code_end#}
2849+
<p>This is equivalent to:</p>
2850+
{#code_begin|syntax#}
2851+
const err = (error {FileNotFound}).FileNotFound;
2852+
{#code_end#}
2853+
<p>
2854+
This becomes useful when using {#link|Inferred Error Sets#}.
2855+
</p>
2856+
{#header_open|The Global Error Set#}
2857+
<p><code>error</code> refers to the global error set.
2858+
This is the error set that contains all errors in the entire compilation unit.
2859+
It is a superset of all other error sets and a subset of none of them.
27992860
</p>
28002861
<p>
2801-
Each error value across the entire compilation unit gets a unique integer,
2802-
and this determines the size of the error set type.
2862+
You can implicitly cast any error set to the global one, and you can explicitly
2863+
cast an error of global error set to a non-global one. This inserts a language-level
2864+
assert to make sure the error value is in fact in the destination error set.
28032865
</p>
28042866
<p>
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.
2867+
The global error set should generally be avoided when possible, because it prevents
2868+
the compiler from knowing what errors are possible at compile-time. Knowing
2869+
the error set at compile-time is better for generated documentationt and for
2870+
helpful error messages such as forgetting a possible error value in a {#link|switch#}.
28072871
</p>
2808-
{#code_begin|syntax#}const pure_error = error.FileNotFound;{#code_end#}
2872+
{#header_close#}
2873+
{#header_close#}
2874+
{#header_open|Error Union Type#}
28092875
<p>
28102876
Most of the time you will not find yourself using an error set type. Instead,
28112877
likely you will be using the error union type. This is when you take an error set
@@ -2918,7 +2984,6 @@ fn doAThing(str: []u8) !void {
29182984
a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the
29192985
application, if there <em>was</em> a surprise error here, the application would crash
29202986
appropriately.
2921-
TODO: mention error return traces
29222987
</p>
29232988
<p>
29242989
Finally, you may want to take a different action for every situation. For that, we combine
@@ -2986,7 +3051,7 @@ fn createFoo(param: i32) !Foo {
29863051
</li>
29873052
</ul>
29883053
{#see_also|defer|if|switch#}
2989-
{#header_open|Error Union Type#}
3054+
29903055
<p>An error union is created with the <code>!</code> binary operator.
29913056
You can use compile-time reflection to access the child type of an error union:</p>
29923057
{#code_begin|test#}
@@ -3008,8 +3073,12 @@ test "error union" {
30083073
comptime assert(@typeOf(foo).ErrorSet == error);
30093074
}
30103075
{#code_end#}
3076+
<p>TODO the <code>||</code> operator for error sets</p>
3077+
{#header_open|Inferred Error Sets#}
3078+
<p>TODO</p>
30113079
{#header_close#}
3012-
{#header_open|Error Set Type#}
3080+
{#header_close#}
3081+
{#header_open|Error Return Traces#}
30133082
<p>TODO</p>
30143083
{#header_close#}
30153084
{#header_close#}

0 commit comments

Comments
 (0)