build: refactor checkGhosttyHEnum to use @hasDecl instead of nested inline for

Replace the O(N×M) nested inline for loop with direct @hasDecl lookups.
The old approach iterated over all translate-c declarations for each enum
field, which required a 10M comptime branch quota on MSVC (2173 decls ×
138 fields × ~20 branches). The new approach constructs the expected
declaration name and checks directly, reducing to O(N) and needing only
100K quota on all platforms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alessandro De Blasis
2026-03-24 20:12:57 +01:00
parent 68378a0bb8
commit 81e21e4d0a

View File

@@ -105,30 +105,27 @@ pub fn checkGhosttyHEnum(
try std.testing.expect(info.@"enum".tag_type == c_int);
try std.testing.expect(info.@"enum".is_exhaustive == true);
@setEvalBranchQuota(10_000_000);
@setEvalBranchQuota(100_000);
const c = @import("ghostty.h");
var set: std.EnumSet(T) = .initFull();
const c_decls = @typeInfo(c).@"struct".decls;
const enum_fields = info.@"enum".fields;
inline for (enum_fields) |field| {
const upper_name = comptime u: {
var buf: [128]u8 = undefined;
break :u std.ascii.upperString(&buf, field.name);
const expected_name: *const [prefix.len + field.name.len]u8 = comptime e: {
var buf: [prefix.len + field.name.len]u8 = undefined;
@memcpy(buf[0..prefix.len], prefix);
for (buf[prefix.len..], field.name) |*d, s| {
d.* = std.ascii.toUpper(s);
}
break :e &buf;
};
inline for (c_decls) |decl| {
if (!comptime std.mem.startsWith(u8, decl.name, prefix)) continue;
const suffix = decl.name[prefix.len..];
if (!comptime std.mem.eql(u8, suffix, upper_name)) continue;
std.testing.expectEqual(field.value, @field(c, decl.name)) catch |e| {
std.log.err(@typeName(T) ++ " key " ++ field.name ++ " does not have the same backing int as " ++ decl.name, .{});
if (@hasDecl(c, expected_name)) {
std.testing.expectEqual(field.value, @field(c, expected_name)) catch |e| {
std.log.err(@typeName(T) ++ " key " ++ field.name ++ " does not have the same backing int as " ++ expected_name, .{});
return e;
};