@@ -2782,30 +2782,96 @@ test "fn reflection" {
2782
2782
{#header_close#}
2783
2783
{#header_close#}
2784
2784
{#header_open|Errors#}
2785
+ {#header_open|Error Set Type#}
2785
2786
<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.
2787
2791
</p>
2788
2792
<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>.
2790
2795
</p>
2791
2796
<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:
2795
2798
</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#}
2796
2821
<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.
2799
2860
</p>
2800
2861
<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.
2803
2865
</p>
2804
2866
<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#}.
2807
2871
</p>
2808
- {#code_begin|syntax#}const pure_error = error.FileNotFound;{#code_end#}
2872
+ {#header_close#}
2873
+ {#header_close#}
2874
+ {#header_open|Error Union Type#}
2809
2875
<p>
2810
2876
Most of the time you will not find yourself using an error set type. Instead,
2811
2877
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 {
2918
2984
a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the
2919
2985
application, if there <em>was</em> a surprise error here, the application would crash
2920
2986
appropriately.
2921
- TODO: mention error return traces
2922
2987
</p>
2923
2988
<p>
2924
2989
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 {
2986
3051
</li>
2987
3052
</ul>
2988
3053
{#see_also|defer|if|switch#}
2989
- {#header_open|Error Union Type#}
3054
+
2990
3055
<p>An error union is created with the <code>!</code> binary operator.
2991
3056
You can use compile-time reflection to access the child type of an error union:</p>
2992
3057
{#code_begin|test#}
@@ -3008,8 +3073,12 @@ test "error union" {
3008
3073
comptime assert(@typeOf(foo).ErrorSet == error);
3009
3074
}
3010
3075
{#code_end#}
3076
+ <p>TODO the <code>||</code> operator for error sets</p>
3077
+ {#header_open|Inferred Error Sets#}
3078
+ <p>TODO</p>
3011
3079
{#header_close#}
3012
- {#header_open|Error Set Type#}
3080
+ {#header_close#}
3081
+ {#header_open|Error Return Traces#}
3013
3082
<p>TODO</p>
3014
3083
{#header_close#}
3015
3084
{#header_close#}
0 commit comments