zig
zig copied to clipboard
Types appear to randomly become const during comptime evaluation involving bound fns
Unfortunately I haven't been able to produce a minimal test case yet, but the problem exists in this branch. Simply run zig test rand.zig and you should see the following output:
/root/git_stdlib-interface_reform_3/std/rand.zig:61:13: error: expected type 'Random(*Xoroshiro128,fn(*Xoroshiro128, []u8) void)', found '*const Random(*Xoroshiro128,fn(*Xoroshiro128, []u8) void)'
self.bytes(rand_bytes[0..]);
^
/root/git_stdlib-interface_reform_3/std/rand.zig:223:63: note: called from here
return if (T == bool) self.boolean() else self.int(T);
^
/root/git_stdlib-interface_reform_3/std/hash_map.zig:536:75: note: called from here
return @truncate(HashInt, unsigned_x ^ comptime rng.scalar(@typeOf(unsigned_x)));
^
/root/git_stdlib-interface_reform_3/std/hash_map.zig:505:28: note: called from here
return autoHash(key, comptime rng.random(), u32);
^
/root/git_stdlib-interface_reform_3/std/rand.zig:36:12: note: Random(*Xoroshiro128,fn(*Xoroshiro128, []u8) void) declared here
return struct {
^
What's happening is that hash_map.zig is using a random number generator at comptime, see lines 501-536, and the Random(T) interface struct is being passed as self to Random(T).scaler(), which then passes it as self to Random(T).int() which then attempts to call self.bytes(), which suddenly decides that self is of type *const Random(T) instead of Random(T)! Adding a @compileLog(@typeOf(self)) immediately before the call confirms that self is, in fact, Random(T).
So far, the only thing that has worked to get around this is to change the call to @typeOf(self).bytes(self, ...);. However, since I don't know what precise circumstances are causing the problem, I feel confident that this is not sufficient.
i threw in these 2 statements and could it be @typeOf() strips away constant which is why it seems to work
diff --git a/std/rand.zig b/std/rand.zig
index 654d1e5b..3ad45cd6 100644
--- a/std/rand.zig
+++ b/std/rand.zig
@@ -58,6 +58,8 @@ pub fn Random(comptime R: type, comptime FillFn: type) type {
var rand_bytes: [@sizeOf(ByteAlignedT)]u8 = undefined;
+@compileLog(self);
+@compileLog(@typeOf(self));
self.bytes(rand_bytes[0..]);
// use LE instead of native endian for better portability maybe?
output
| (struct Random(*Xoroshiro128,fn(*Xoroshiro128, []u8) void) constant)
| Random(*Xoroshiro128,fn(*Xoroshiro128, []u8) void)
I can confirm that this is a comptime issue by making all the comptime references to the interface runtime instead and indeed tests now appear to run fine.
Additionally I will add that using non-method call syntax doesn't really solve the issue, it just moves it:
/root/git_stdlib-interface_reform_3/std/rand.zig:663:19: error: cannot assign to constant
self.s[0] = math.rotl(u64, s0, u8(55)) ^ s1 ^ (s1 << 14);
^
/root/git_stdlib-interface_reform_3/std/rand.zig:718:30: note: called from here
var n = self.next();
^
/root/git_stdlib-interface_reform_3/std/rand.zig:46:24: note: called from here
self.fillFn(self.impl, buf);
^
/root/git_stdlib-interface_reform_3/std/rand.zig:61:23: note: called from here
self.bytes(rand_bytes[0..]);
^
/root/git_stdlib-interface_reform_3/std/rand.zig:223:63: note: called from here
return if (T == bool) self.boolean() else self.int(T);
^
/root/git_stdlib-interface_reform_3/std/hash_map.zig:534:65: note: called from here
return HashInt(unsigned_x) ^ comptime rng.scalar(HashInt);
^
/root/git_stdlib-interface_reform_3/std/hash_map.zig:505:28: note: called from here
return autoHash(key, comptime rng.random(), u32);
^
Bound functions have been removed.