commit 5a376d97d4595f12dffaf54c4cfc303b0e902cc6 (tree)
parent 0b3b536f18957979374a00b2411943b4a37beb0f
Author: Justus Klausecker <justus@klausecker.de>
Date: Sat, 10 Jan 2026 14:57:23 +0100
langref: document new switch features
- switch on tagged union with runtime-captured tag
- switch on errors special cases
Diffstat:
3 files changed, 70 insertions(+), 4 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
@@ -2461,7 +2461,8 @@ or
{#header_open|Tagged union#}
<p>Unions can be declared with an enum tag type.
This turns the union into a <em>tagged</em> union, which makes it eligible
- to use with {#link|switch#} expressions.
+ to use with {#link|switch#} expressions. When switching on tagged unions,
+ the tag value can be obtained using an additional capture.
Tagged unions coerce to their tag type: {#link|Type Coercion: Unions and Enums#}.
</p>
{#code|test_tagged_union.zig#}
@@ -2594,6 +2595,13 @@ or
{#header_close#}
+ {#header_open|Switching on errors#}
+ <p>
+ When switching on errors, some special cases are allowed to simplify generic programming patterns:
+ </p>
+ {#code|test_switch_on_errors.zig#}
+ {#header_close#}
+
{#header_open|Labeled switch#}
<p>
When a switch statement is labeled, it can be referenced from a
@@ -2659,12 +2667,13 @@ or
{#code|test_inline_else.zig#}
<p>
- When using an inline prong switching on an union an additional
- capture can be used to obtain the union's enum tag value.
+ When using an inline prong switching on an union an additional capture
+ can be used to obtain the union's enum tag value at comptime, even though
+ its payload might only be known at runtime.
</p>
{#code|test_inline_switch_union_tag.zig#}
- {#see_also|inline while|inline for#}
+ {#see_also|inline while|inline for|Tagged union#}
{#header_close#}
{#header_close#}
diff --git a/doc/langref/test_switch_on_errors.zig b/doc/langref/test_switch_on_errors.zig
@@ -0,0 +1,52 @@
+const FileOpenError0 = error{
+ AccessDenied,
+ OutOfMemory,
+ FileNotFound,
+};
+
+fn openFile0() FileOpenError0 {
+ return error.OutOfMemory;
+}
+
+test "unreachable else prong" {
+ switch (openFile0()) {
+ error.AccessDenied, error.FileNotFound => |e| return e,
+ error.OutOfMemory => {},
+ else => unreachable, // technically unreachable, but will still compile!
+ }
+
+ // Allowed unreachable else prongs are:
+ // `else => unreachable,`
+ // `else => return,`
+ // `else => |e| return e,` (where `e` is any identifier)
+}
+
+const FileOpenError1 = error{
+ AccessDenied,
+ SystemResources,
+ FileNotFound,
+};
+
+fn openFile1() FileOpenError1 {
+ return error.SystemResources;
+}
+
+fn openFileGeneric(comptime kind: u1) switch (kind) {
+ 0 => FileOpenError0,
+ 1 => FileOpenError1,
+} {
+ return switch (kind) {
+ 0 => openFile0(),
+ 1 => openFile1(),
+ };
+}
+
+test "comptime unreachable errors not in error set" {
+ switch (openFileGeneric(1)) {
+ error.AccessDenied, error.FileNotFound => |e| return e,
+ error.OutOfMemory => comptime unreachable, // not in `FileOpenError1`!
+ error.SystemResources => {},
+ }
+}
+
+// test
diff --git a/doc/langref/test_tagged_union.zig b/doc/langref/test_tagged_union.zig
@@ -18,6 +18,11 @@ test "switch on tagged union" {
.ok => |value| try expect(value == 42),
.not_ok => unreachable,
}
+
+ switch (c) {
+ .ok => |_, tag| try expect(tag == .ok),
+ .not_ok => unreachable,
+ }
}
test "get tag type" {