zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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