ratfactor/ziglings

Exercise 74: the comptime statement is no longer needed in the latest zig version

chrboesch opened this issue ยท 7 comments

I ran exercise 74 with zig version 0.10.0-dev.3672+cd5a9ba1f without any changes on the source and got

PASSED:
My llama value is 2.

๐Ÿค”

You wrote "..it's sometimes surprising how few places actually need the keyword." Now it's one less. ๐Ÿ˜‰

LOL. Thanks!

Summary: a regression in the self-hosted compiler


makeLlamas is only called at compile time because it is used for a global variable initialization value. In order to restore the example, put the variable declaration inside a function block like this:

--- a/exercises/074_comptime9.zig
+++ b/exercises/074_comptime9.zig
@@ -32,11 +32,6 @@ const print = @import("std").debug.print;
 // implicitly required to be known compile time.
 const llama_count = 5;
 
-// Again, this value's type and size must be known at compile
-// time, but we're letting the compiler infer both from the
-// return type of a function.
-const llamas = makeLlamas(llama_count);
-
 // And here's the function. Note that the return value type
 // depends on one of the input arguments!
 fn makeLlamas(count: usize) [count]u8 {
@@ -52,6 +47,11 @@ fn makeLlamas(count: usize) [count]u8 {
 }
 
 pub fn main() void {
+    // Again, this value's type and size must be known at compile
+    // time, but we're letting the compiler infer both from the
+    // return type of a function.
+    const llamas = makeLlamas(llama_count);
+
     print("My llama value is {}.\n", .{llamas[2]});
 }
 //

However, with this, the error becomes:

test.zig:39:9: error: variable of type 'comptime_int' must be const or comptime
    var i = 0;
        ^
test.zig:39:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type
test.zig:53:30: note: called from here
    const llamas = makeLlamas(llama_count);
                   ~~~~~~~~~~^~~~~~~~~~~~~

This happens because zig is trying to generate a makeLlamas function that can be called at runtime. The intended solution no longer works with a runtime call to the function; it gives the same error as above.

With makeLlamas only called at compile-time, as in status quo, the new behavior is correct! Ironically the central point of the lesson rings even more true.

As for a suggestion on how to restore the exercise, I'm actually not sure, because when I make the following change...

-    var i = 0;
+    var i: u8 = 0;

...I noticed that it still passes, despite no use of the comptime keyword. After examining this closely, I discovered that in this case, Zig is inlining the function call to makeLlamas when no comptime keyword is present. This is suspicious behavior, so I will examine the related code carefully in search for an analysis bug. Thanks for pinging me!

Bug filed upstream: ziglang/zig#12679

Thanks to @Vexu this issue is fixed in Zig master branch. Ziglings exercise 074 now gives:

test.zig:42:30: error: unable to resolve comptime value
fn makeLlamas(count: usize) [count]u8 {
                             ^~~~~
test.zig:42:30: note: array length must be comptime known

Which arguably is an improvement over stage1:

./test.zig:42:30: error: use of undeclared identifier 'count'
fn makeLlamas(count: usize) [count]u8 {
                             ^

The original intended solution now works for stage2 as well as stage1.

Furthermore, the makeLlamas function has found its way into the Zig compiler test suite ๐Ÿ™‚

Awesome, @andrewrk , thanks for the excellent write-up! And I'm laughing with joy that ๐Ÿฆ™ ๐Ÿฆ™ ๐Ÿฆ™ makeLlamas() ๐Ÿฆ™ ๐Ÿฆ™ ๐Ÿฆ™ is now a Zig compiler test. ๐Ÿคฃ

@andrewrk Thank you very much!

Yahoo! The upstream fix is now in the master build. I've bumped the Ziglings minimum version requirement to 0.10.0-dev.3880+. Thanks again for catching this, @chrboesch !