Skip to content

Commit

Permalink
update errors section of docs
Browse files Browse the repository at this point in the history
closes #768
  • Loading branch information
andrewrk committed Feb 24, 2018
1 parent b66547e commit 8db7a14
Showing 1 changed file with 84 additions and 15 deletions.
99 changes: 84 additions & 15 deletions doc/langref.html.in
Expand Up @@ -2782,30 +2782,96 @@ test "fn reflection" {
{#header_close#}
{#header_close#}
{#header_open|Errors#}
{#header_open|Error Set Type#}
<p>
One of the distinguishing features of Zig is its exception handling strategy.
An error set is like an {#link|enum#}.
However, each error name across the entire compilation gets assigned an unsigned integer
greater than 0. You are allowed to declare the same error name more than once, and if you do, it
gets assigned the same integer value.
</p>
<p>
TODO rewrite the errors section to take into account error sets
The number of unique error values across the entire compilation should determine the size of the error set type.
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>.
</p>
<p>
These error values are assigned an unsigned integer value greater than 0 at
compile time. You are allowed to declare the same error value more than once,
and if you do, it gets assigned the same integer value.
You can implicitly cast an error from a subset to its superset:
</p>
{#code_begin|test#}
const std = @import("std");

const FileOpenError = error {
AccessDenied,
OutOfMemory,
FileNotFound,
};

const AllocationError = error {
OutOfMemory,
};

test "implicit cast subset to superset" {
const err = foo(AllocationError.OutOfMemory);
std.debug.assert(err == FileOpenError.OutOfMemory);
}

fn foo(err: AllocationError) FileOpenError {
return err;
}
{#code_end#}
<p>
You can refer to these error values with the error namespace such as
<code>error.FileNotFound</code>.
But you cannot implicitly cast an error from a superset to a subset:
</p>
{#code_begin|test_err|not a member of destination error set#}
const FileOpenError = error {
AccessDenied,
OutOfMemory,
FileNotFound,
};

const AllocationError = error {
OutOfMemory,
};

test "implicit cast superset to subset" {
foo(FileOpenError.OutOfMemory) catch {};
}

fn foo(err: FileOpenError) AllocationError {
return err;
}
{#code_end#}
<p>
There is a shortcut for declaring an error set with only 1 value, and then getting that value:
</p>
{#code_begin|syntax#}
const err = error.FileNotFound;
{#code_end#}
<p>This is equivalent to:</p>
{#code_begin|syntax#}
const err = (error {FileNotFound}).FileNotFound;
{#code_end#}
<p>
This becomes useful when using {#link|Inferred Error Sets#}.
</p>
{#header_open|The Global Error Set#}
<p><code>error</code> refers to the global error set.
This is the error set that contains all errors in the entire compilation unit.
It is a superset of all other error sets and a subset of none of them.
</p>
<p>
Each error value across the entire compilation unit gets a unique integer,
and this determines the size of the error set type.
You can implicitly cast any error set to the global one, and you can explicitly
cast an error of global error set to a non-global one. This inserts a language-level
assert to make sure the error value is in fact in the destination error set.
</p>
<p>
The error set type is one of the error values, and in the same way that pointers
cannot be null, a error set instance is always an error.
The global error set should generally be avoided when possible, because it prevents
the compiler from knowing what errors are possible at compile-time. Knowing
the error set at compile-time is better for generated documentationt and for
helpful error messages such as forgetting a possible error value in a {#link|switch#}.
</p>
{#code_begin|syntax#}const pure_error = error.FileNotFound;{#code_end#}
{#header_close#}
{#header_close#}
{#header_open|Error Union Type#}
<p>
Most of the time you will not find yourself using an error set type. Instead,
likely you will be using the error union type. This is when you take an error set
Expand Down Expand Up @@ -2918,7 +2984,6 @@ fn doAThing(str: []u8) !void {
a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the
application, if there <em>was</em> a surprise error here, the application would crash
appropriately.
TODO: mention error return traces
</p>
<p>
Finally, you may want to take a different action for every situation. For that, we combine
Expand Down Expand Up @@ -2986,7 +3051,7 @@ fn createFoo(param: i32) !Foo {
</li>
</ul>
{#see_also|defer|if|switch#}
{#header_open|Error Union Type#}

<p>An error union is created with the <code>!</code> binary operator.
You can use compile-time reflection to access the child type of an error union:</p>
{#code_begin|test#}
Expand All @@ -3008,8 +3073,12 @@ test "error union" {
comptime assert(@typeOf(foo).ErrorSet == error);
}
{#code_end#}
<p>TODO the <code>||</code> operator for error sets</p>
{#header_open|Inferred Error Sets#}
<p>TODO</p>
{#header_close#}
{#header_open|Error Set Type#}
{#header_close#}
{#header_open|Error Return Traces#}
<p>TODO</p>
{#header_close#}
{#header_close#}
Expand Down

0 comments on commit 8db7a14

Please sign in to comment.