Nested fn?

Hi guys,

legal or undefined behavior? It seems the x is freed, but the program does not crash.

const print = @import("std").debug.print;

pub fn main() void {
    bar()();
}

fn bar() fn () void {
    const x: [4]u8 = .{ 1, 2, 3, 4 };
    return enum {
        fn hello() void {
            for (x) |y| {
                print("nested fn? {}\n", .{y});
            }
        }
    }.hello;
}

x is known at comptime, if it were runtime known (which you can do with var, and a _ = &x to silence the not mutated error), then you will get a compile error for trying to capture a runtime var in a comptime expression (the function/type definition)

Also, struct is typically used for this, it doesn’t matter unless you want it to be an instantiable type, just curious.

5 Likes

x is a comptime const value here, so it is feasible; if it were known at runtime, it would not be feasible.

something that will help you a lot in your Zig journey is to realize the following: Zig eagerly evaluates code at compile time. With the exception, basically, of calling functions. If anything you have written can be said to be compile-time known, it will be treated as such.

Now, in the event that x is a runtime local variable, I would also prefer the phrasing “x goes out of scope”: like all stack variables, it is not really subject to alloc/free semantics

4 Likes