zig
zig copied to clipboard
Bad type inference for function pointers
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;
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.