a73x

66d33148

refactor: cliflags says its two comptime gates in fewer lines

a73x   2026-08-27 07:53

Commit message
refactor: cliflags says its two comptime gates in fewer lines

`Bare` was a two-arm switch for what is one question, and the alias gate
wrapped a comptime loop in a comptime block. Both gates still refuse:
mutating an alias to name no field, and a field to a struct with no
parseCLI, each fails the compile with the line it always did.

The word loop itself is left alone — classifying each word once and then
dispatching wants an enum and a classify function, and costs more lines
than the branches it would replace.

src/cli/flags.zig
Old New
@@ -24,10 +24,7 @@ pub const Outcome = union(enum) {
24 24
25 /// An optional field is its child type: null is a default, not an arity. 25 /// An optional field is its child type: null is a default, not an arity.
26 fn Bare(comptime F: type) type { 26 fn Bare(comptime F: type) type {
27 return switch (@typeInfo(F)) { 27 return if (@typeInfo(F) == .optional) @typeInfo(F).optional.child else F;
28 .optional => |o| o.child,
29 else => F,
30 };
31 } 28 }
32 29
33 /// A flag given twice: the last wins. A word that is not a flag is offered 30 /// A flag given twice: the last wins. A word that is not a flag is offered
@@ -46,12 +43,10 @@ pub fn parse(comptime T: type, dst: *T, args: []const [:0]const u8) Outcome {
46 if (B != bool and B != []const u8 and @typeInfo(B) != .int and !owns) 43 if (B != bool and B != []const u8 and @typeInfo(B) != .int and !owns)
47 @compileError("cliflags: no arity for field `" ++ f.name ++ "`: " ++ @typeName(f.type)); 44 @compileError("cliflags: no arity for field `" ++ f.name ++ "`: " ++ @typeName(f.type));
48 }; 45 };
49 comptime { 46 if (@hasDecl(T, "aliases")) comptime for (T.aliases) |pair| {
50 if (@hasDecl(T, "aliases")) for (T.aliases) |pair| { 47 if (!@hasField(T, pair[1]))
51 if (!@hasField(T, pair[1])) 48 @compileError("cliflags: alias `" ++ pair[0] ++ "` names no field `" ++ pair[1] ++ "`");
52 @compileError("cliflags: alias `" ++ pair[0] ++ "` names no field `" ++ pair[1] ++ "`"); 49 };
53 };
54 }
55 50
56 // Asked for before anything is read, so that a `--help` sitting where a 51 // Asked for before anything is read, so that a `--help` sitting where a
57 // value belongs still answers with the usage instead of being eaten. 52 // value belongs still answers with the usage instead of being eaten.