zig icon indicating copy to clipboard operation
zig copied to clipboard

Bad type inference for function pointers

Open lambdadog opened this issue 3 years ago • 1 comments

Zig Version

0.11.0-dev.48+678f3f6e6

Steps to Reproduce and Observed Behavior

// repro.zig
const std = @import("std");
const RndGen = std.rand.DefaultPrng;

pub fn main() void {
    var rng = RndGen.init(0);
    const fnPointer = if (rng.random().boolean()) fnOne else fnTwo;
    fnPointer();
}

fn fnOne() void {
    std.log.info("fnOne", .{});
}

fn fnTwo() void {
    std.log.info("fnTwo", .{});
}
$ zig run repro.zig
repro.zig:6:23: error: value with comptime-only type 'fn() void' depends on runtime control flow
    const fnPointer = if (rng.random().boolean()) fnOne else fnTwo;
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
repro.zig:6:47: note: runtime control flow here
    const fnPointer = if (rng.random().boolean()) fnOne else fnTwo;
                          ~~~~~~~~~~~~~~~~~~~~^~
repro.zig:6:23: note: use '*const fn() void' for a function pointer type
referenced by:
    callMain: /nix/store/lxyakhpd2jv5d98f7yx8i0sfncjawa06-zig-0.11.0-dev.48+678f3f6e6/lib/std/start.zig:604:17
    initEventLoopAndCallMain: /nix/store/lxyakhpd2jv5d98f7yx8i0sfncjawa06-zig-0.11.0-dev.48+678f3f6e6/lib/std/start.zig:548:51
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

Expected Behavior

I expected Zig to correctly perform type inference and infer the type *const fn () void for fnPointer. Instead it infers fn () void, which is only acceptable for the bootstrapping compiler as per 0.10.0 release notes and explicit type annotation is required:

const fnPointer: *const fn () void = if (rng.random().boolean()) fnOne else fnTwo;

lambdadog avatar Nov 04 '22 03:11 lambdadog

The example is working as expected since fn () void is a perfectly valid type, however adding & to one of the functions should make the peer type resolution work.

Vexu avatar Nov 04 '22 13:11 Vexu