What is the caching strategy for Zig's generic functions?

For the following Zig code:

pub fn Box(comptime N: usize) type {
    @compileLog(N);
    if (N > 100) {
        return struct {
            pub const K = u32;
        };
    } else {
        return struct {
            pub const M = f64;
        };
    }
}

test "Box" {
    const A = Box(10);
    const B = Box(200);
    const C = Box(50);
    const D = Box(10);

    @compileLog(A);
    @compileLog(B);
    @compileLog(C);
    @compileLog(D);

    @compileLog(A == B);
    @compileLog(A == C);
    @compileLog(B == C);
}

I have received the output:

1.zig:2:5: error: found compile log statement
    @compileLog(N);
    ^~~~~~~~~~~~~~

Compile Log Output:
@as(usize, 10)
@as(usize, 200)
@as(usize, 50)
@as(type, 1.Box(10))
@as(type, 1.Box(200))
@as(type, 1.Box(10))
@as(type, 1.Box(10))
@as(bool, false)
@as(bool, true)
@as(bool, false)

What is Zig’s caching strategy for generic functions that I am curious about?

The caching for the function call is the argument values, you can see that with the compile log in the function.

And user defined/generic type equivalence is based on 1) the source location and 2) the comptime values it captures.

Which you can see with your other compile logs and type comparisons.

I think whether it is cached depends on the inside of struct{...}, specifically whether this parameter is involved in the computation in any form.

For example, the result of this Box2 is quite different, because N enters inside struct{...}, even though N has no substantial effect on the result.
.

pub fn Box2(comptime N: usize) type {
    @compileLog(N);
    if (N > 100) {
        return struct {
            pub const K = u32;
            pub const v: usize = 0 + N - N;
        };
    } else {
        return struct {
            pub const M = f64;
            pub const v: usize = 0 + N - N;
        };
    }
}

test "Box2" {
    const A = Box2(10);
    const B = Box2(200);
    const C = Box2(50);
    const D = Box2(10);

    @compileLog(A);
    @compileLog(B);
    @compileLog(C);
    @compileLog(D);

    @compileLog(A == B);
    @compileLog(A == C);
    @compileLog(B == C);
}
Compile Log Output:
@as(usize, 10)
@as(usize, 200)
@as(usize, 50)
@as(type, 1.Box2(10))
@as(type, 1.Box2(200))
@as(type, 1.Box2(50))
@as(type, 1.Box2(10))
@as(bool, false)
@as(bool, false)
@as(bool, false)
1 Like