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