const std = @import("std"); const expect = std.testing.expect; const expectError = std.testing.expectError; fn isFieldOptional(comptime T: type, field_index: usize) !bool { const fields = @typeInfo(T).@"struct".fields; return switch (field_index) { // This prong is analyzed twice with `idx` being a // comptime-known value each time. inline 0, 1 => |idx| @typeInfo(fields[idx].type) == .optional, else => return error.IndexOutOfBounds, }; } const Struct1 = struct { a: u32, b: ?u32 }; test "using @typeInfo with runtime values" { var index: usize = 0; try expect(!try isFieldOptional(Struct1, index)); index += 1; try expect(try isFieldOptional(Struct1, index)); index += 1; try expectError(error.IndexOutOfBounds, isFieldOptional(Struct1, index)); } // Calls to `isFieldOptional` on `Struct1` get unrolled to an equivalent // of this function: fn isFieldOptionalUnrolled(field_index: usize) !bool { return switch (field_index) { 0 => false, 1 => true, else => return error.IndexOutOfBounds, }; } // test