master
 1const std = @import("std");
 2const expect = std.testing.expect;
 3
 4const SliceTypeA = extern struct {
 5    len: usize,
 6    ptr: [*]u32,
 7};
 8const SliceTypeB = extern struct {
 9    ptr: [*]SliceTypeA,
10    len: usize,
11};
12const AnySlice = union(enum) {
13    a: SliceTypeA,
14    b: SliceTypeB,
15    c: []const u8,
16    d: []AnySlice,
17};
18
19fn withFor(any: AnySlice) usize {
20    const Tag = @typeInfo(AnySlice).@"union".tag_type.?;
21    inline for (@typeInfo(Tag).@"enum".fields) |field| {
22        // With `inline for` the function gets generated as
23        // a series of `if` statements relying on the optimizer
24        // to convert it to a switch.
25        if (field.value == @intFromEnum(any)) {
26            return @field(any, field.name).len;
27        }
28    }
29    // When using `inline for` the compiler doesn't know that every
30    // possible case has been handled requiring an explicit `unreachable`.
31    unreachable;
32}
33
34fn withSwitch(any: AnySlice) usize {
35    return switch (any) {
36        // With `inline else` the function is explicitly generated
37        // as the desired switch and the compiler can check that
38        // every possible case is handled.
39        inline else => |slice| slice.len,
40    };
41}
42
43test "inline for and inline else similarity" {
44    const any = AnySlice{ .c = "hello" };
45    try expect(withFor(any) == 5);
46    try expect(withSwitch(any) == 5);
47}
48
49// test