std.Build.option: Improve type detection logic
Improves the type detection logic of option to more accurately raise errors for all invalid types.
Currently, passing any pointer-to-u8 or pointer-to-enum type other than []const u8 or []const AnEnum raises unhelpful compile errors elsewhere in the code.
(split from original #20412)
Can you show some examples that you tested this with? I'm not convinced this approach is better than using @typeInfo.
Example of a simple project made with zig init, with the following build.zig:
const std = @import("std");
const Enum = enum { a, b, c };
pub fn build(b: *std.Build) void {
_ = b.option([:0]u8, "string", "");
_ = b.option(*Enum, "enum", "");
}
Status-quo raises those errors:
error: expected type '?[:0]u8', found '[]const u8'
error: expected type '?*build.Enum', found '[]build.Enum'
With this note:
note: function return type declared here
pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
^~
This is due to the fact that the current logic only checks the child type of the pointer types passed; the logic of this branch restricts the accepted types to more accurately map the argument to TypeId while emitting the correct error:
error: Unsupported type: []u8
error: Unsupported type: *build.Enum
The behaviour is identical for those cases:
const std = @import("std");
const Enum = enum { a, b, c };
pub fn build(b: *std.Build) void {
// Compile and run successfully
_ = b.option(std.zig.BuildId, "build_id", "");
_ = b.option(bool, "flag", "");
_ = b.option(i32, "int", "");
_ = b.option(f32, "float", "");
_ = b.option([]const u8, "string", "");
_ = b.option([]const []const u8, "list", "");
_ = b.option(Enum, "enum", "");
_ = b.option([]const Enum, "enum_list", "");
// Emit accurate errors
_ = b.option(void, "void", "");
_ = b.option(struct {}, "struct", "");
_ = b.option(error{Example}, "error", "");
}
Sorry, it bitrotted before I got around to it.