langref: document new switch features

- switch on tagged union with runtime-captured tag
- switch on errors special cases
This commit is contained in:
Justus Klausecker 2026-01-10 14:57:23 +01:00 committed by Matthew Lugg
parent 0b3b536f18
commit 5a376d97d4
No known key found for this signature in database
GPG key ID: 3F5B7DCCBF4AF02E
3 changed files with 70 additions and 4 deletions

View file

@ -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#}

View file

@ -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

View file

@ -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" {