zig icon indicating copy to clipboard operation
zig copied to clipboard

std.Build.option: Improve type detection logic

Open Lzard opened this issue 1 year ago • 2 comments

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)

Lzard avatar Jun 27 '24 10:06 Lzard

Can you show some examples that you tested this with? I'm not convinced this approach is better than using @typeInfo.

andrewrk avatar Jul 21 '24 09:07 andrewrk

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", "");
}

Lzard avatar Jul 21 '24 09:07 Lzard

Sorry, it bitrotted before I got around to it.

andrewrk avatar Jul 17 '25 03:07 andrewrk