test_inline_else.zig (1372B) - Raw
1 const std = @import("std"); 2 const expect = std.testing.expect; 3 4 const SliceTypeA = extern struct { 5 len: usize, 6 ptr: [*]u32, 7 }; 8 const SliceTypeB = extern struct { 9 ptr: [*]SliceTypeA, 10 len: usize, 11 }; 12 const AnySlice = union(enum) { 13 a: SliceTypeA, 14 b: SliceTypeB, 15 c: []const u8, 16 d: []AnySlice, 17 }; 18 19 fn 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 34 fn 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 43 test "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