Skip to content

false positive circular dependency when a comptime-called function has function as a return type that uses generic parameters from the outer function #11367

@andrewrk

Description

@andrewrk

Zig Version: 0.10.0-dev.1694+ecd756834

test {
    var map: HashMapUnmanaged(AutoContext(*Decl)) = .{};
    _ = map;
}

const Decl = struct {
    namespace: *Namespace,
};

const Namespace = struct {
    decls: HashMapUnmanaged(AutoContext(*Decl)),
};

fn getFn(comptime K: type) (fn (K) u64) {
    return struct {
        fn hash(key: K) u64 {
            _ = key;
            return 1234;
        }
    }.hash;
}

fn AutoContext(comptime K: type) type {
    return struct {
        const hash = getFn(K);
    };
}

fn HashMapUnmanaged(comptime Context: type) type {
    comptime verifyContext(Context);
    return struct {};
}

fn verifyContext(comptime Context: type) void {
    const hash = Context.hash;
    _ = hash;
}

Expected to pass. Instead:

$ ./stage2/bin/zig test test3.zig 
test3.zig:28:9: error: 'hash' depends on itself
        const hash = getFn(K);
        ^

This happens because:

  • verifyContext tries to look at the hash function, invoking comptime getFn.
  • while evaluating the return type of getFn, zig tries to check if K is a comptime-only type.
  • K is *Decl so to check if it is a comptime-only type, it looks at Decl fields types, and then recursively looks at Namespace field types.
  • HashMapUnmanaged(AutoContext(*Decl)) is comptime-evaluated
  • verifyContext is again called at comptime for the same parameters (the previous call is still ongoing)
  • hash is still wip but we are trying to look at it again.

A workaround is placing the comptime call to verifyContext inside the struct rather than before it:

fn HashMapUnmanaged(comptime Context: type) type {
    return struct {
        comptime {
            verifyContext(Context);
        }
    };
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorfrontendTokenization, parsing, AstGen, Sema, and Liveness.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions