What am I doing wrong here?
const std = @import("std");
const testing = std.testing;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const value = toValue(10)(allocator, 20);
std.debug.print("All your {s} are belong to us.\n", .{value});
}
fn toValue(comptime value: anytype) fn (std.mem.Allocator, anytype) anyerror!@TypeOf(value) {
return struct {
fn toValue(_: std.mem.Allocator, _: anytype) !@TypeOf(value) {
return value;
}
}.toValue;
}
test "toValue" {
const allocator = testing.failing_allocator;
try testing.expectEqual(10, toValue(10)(allocator, 20));
try testing.expectEqualStrings("foo", toValue("foo")(allocator, "bar"));
}
Because I get a transitive failure, even though I’m not using any dependencies.
❯ zig build
install
└─ install test
└─ zig build-exe test Debug native failure
error: the following command terminated unexpectedly:
/usr/local/bin/zig build-exe -ODebug -Mroot=/Users/joelr/Work/Zig/test/src/main.zig --cache-dir /Users/joelr/Work/Zig/test/.zig-cache --global-cache-dir /Users/joelr/.cache/zig --name test --zig-lib-dir /usr/local/lib/zig/ --listen=-
Build Summary: 0/3 steps succeeded; 1 failed
install transitive failure
└─ install test transitive failure
└─ zig build-exe test Debug native failure
error: the following build command failed with exit code 1:
/Users/joelr/Work/Zig/test/.zig-cache/o/4ae0111ced83033f2da7f7f079d783c5/build /usr/local/bin/zig /usr/local/lib/zig /Users/joelr/Work/Zig/test /Users/joelr/Work/Zig/test/.zig-cache /Users/joelr/.cache/zig --seed 0xe512834 -Zd0358ae2a1e6601d
Not an issue with testing because building this
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const value = toValue(10)(allocator, 20);
std.debug.print("All your {s} are belong to us.\n", .{value});
}
fn toValue(comptime value: anytype) fn (std.mem.Allocator, anytype) anyerror!@TypeOf(value) {
return struct {
fn toValue(_: std.mem.Allocator, _: anytype) !@TypeOf(value) {
return value;
}
}.toValue;
}
still gives me this error
❯ zig build
install
└─ install test
└─ zig build-exe test Debug native failure
error: the following command terminated unexpectedly:
/usr/local/bin/zig build-exe -ODebug -Mroot=/Users/joelr/Work/Zig/test/src/main.zig --cache-dir /Users/joelr/Work/Zig/test/.zig-cache --global-cache-dir /Users/joelr/.cache/zig --name test --zig-lib-dir /usr/local/lib/zig/ --listen=-
Build Summary: 0/3 steps succeeded; 1 failed
install transitive failure
└─ install test transitive failure
└─ zig build-exe test Debug native failure
error: the following build command failed with exit code 1:
/Users/joelr/Work/Zig/test/.zig-cache/o/4ae0111ced83033f2da7f7f079d783c5/build /usr/local/bin/zig /usr/local/lib/zig /Users/joelr/Work/Zig/test /Users/joelr/Work/Zig/test/.zig-cache /Users/joelr/.cache/zig --seed 0x55c54982 -Z381019e07a3ef546
n0s4
October 29, 2024, 2:12pm
3
I’ve tried reducing your program, and at some point the transitive failure turns into an OutOfMemory
error. I think this is a Zig bug:
const std = @import("std");
pub fn main() void {
_ = &toValue(10);
}
fn toValue(comptime value: anytype) fn (anytype) @TypeOf(value) {
return struct {
fn toValue(_: anytype) @TypeOf(value) {
return value;
}
}.toValue;
}
$ zig build run
run
└─ run t
└─ zig build-exe t Debug native failure
error: error: OutOfMemory
error: the following command exited with error code 1:
/home/joe/.local/bin/zig build-exe -ODebug -Mroot=/home/joe/dev/test/t/src/main.zig --cache-dir /home/joe/dev/test/t/.zig-cache --global-cache-dir /home/joe/.cache/zig --name t --zig-lib-dir /home/joe/.local/lib/zig/ --listen=-
Build Summary: 2/7 steps succeeded; 1 failed
run transitive failure
└─ run t transitive failure
├─ zig build-exe t Debug native failure
└─ install transitive failure
└─ install t transitive failure
└─ zig build-exe t Debug native (reused)
error: the following build command failed with exit code 1:
/home/joe/dev/test/t/.zig-cache/o/d6ab6ac316016b1fb96986f35985df59/build /home/joe/.local/bin/zig /home/joe/.local/lib/zig /home/joe/dev/test/t /home/joe/dev/test/t/.zig-cache /home/joe/.cache/zig --seed 0xcf2b4b4d -Zfb3c70f1c60d0fa9 run
Possibly an issue with resolving the type of the anytype
parameter.
Let report it then…
Also, any suggestions on how I can achieve what I’m trying to do, i.e. return a value from a closure ?
n0s4
October 29, 2024, 2:20pm
5
What are you trying to achieve with toValue
?
I’m not clear on what exactly your intent is with this, but I have a suspicion that you meant to take a type
parameter for toValue
rather than anytype
(“a value of any type”).
I’m trying to have a Mecha parser return a given value, e.g.
const eqOp = m.oneOf(.{
_eq.map(toValue(.eq)),
_neq.map(toValue(.neq)),
});
const EqOp = enum { eq, neq };
There’s a toEnum
conversion function but that requires me to use eq
and neq
in expressions I’m trying to parse, not ==
and !=
.
The value I want to return is specified at parse construction (compile) time and I’m ignoring the allocator and parsed value given to me at runtime by Mecha.
P.S. I filed a bug report .
This works but depends on the parser feeding in a string.
fn toValue(comptime T: type, value: T) fn (std.mem.Allocator, []const u8) anyerror!T {
return struct {
fn toValue(_: std.mem.Allocator, _: []const u8) anyerror!T {
return value;
}
}.toValue;
}