So in this case we will always have to declare the type now? Feels like StaticStringMap should already know the type of the second argument as it accepts a key value pair of <[]const u8, T>, but I guess the compiler doesn’t know that this anonymous struct should be T?
Looking at implementation details the reason for the anonymous struct to not be coerced into T is because the function initComptime was designed to accept struct { []const u8 } too so the signature of the function looks like:
/// Returns a map backed by static, comptime allocated memory.
///
/// `kvs_list` must be either a list of `struct { []const u8, V }`
/// (key-value pair) tuples, or a list of `struct { []const u8 }`
/// (only keys) tuples if `V` is `void`.
pub inline fn initComptime(comptime kvs_list: anytype) Self {
No it accepts an anytype, if it took a slice you’d need an & in front of the outer literal, if it took an array you’d need to pass the length as a separate comptime argument since that couldn’t be inferred.
Because its anytype it has no destination type to infer from, the result it an anonymous struct type.
Before, it could incorrectly be coerced to the actual type, an implicit changing of types. That is not allowed per the language design. It was a compiler bug.
I agree before it could incorrectly coerce to the wrong type. I was trying to ask about API design, because if the function signature was pub inline fn initComptime(comptime kvs_list: struct { []const u8, V }) Self { then the type could always be coerced correctly?
Mostly wondering about the use case of having a StaticStringMap with only keys and no values. Without that requirement the usage of it would be nicer.
One problem with []const KV is that you couldn’t just specify the keys anymore, you also would have to specify the field names including the one for the void value field.
One alternative could be to use a tagged union to separate between the two valid cases accepted by the function:
It seems like the easier option is to just leave StaticStringMap the way it is and use an explicit array type, so @nm-remarkable’s example would become:
const presetMap = std.StaticStringMap(std.Target.Query).initComptime([_]struct{[]const u8, std.Target.Query}{
.{ "arm-linux", .{ .cpu_arch = .aarch64, .os_tag = .linux } },
.{ "native", .{} },
.{ "linux", .{ .cpu_arch = .x86_64, .os_tag = .linux } }, // to be used for wsl on windows
});