Open GrooveStomp opened 4 years ago
And, OS specifics, for reference:
Linux pop-os 5.3.0-19-generic #20-Ubuntu SMP Fri Oct 18 09:04:39 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Switching over function types is not supported as the effective address of a function is not known until link-time.
@andrewrk maybe it's time to define what types are accepted by switch
Switching over function types is not supported as the effective address of a function is not known until link-time.
What's the reason why the compiler can't just stub these out for the linker. eg. just jump to a label or whatever address the linker fills in (even as part of LTO)? It would be very nice to not have this be a limitation, especially if Zig wants to allure OOP programmers.
What's the reason why the compiler can't just stub these out for the linker.
Switch lowering is a delicate and complex matter and LLVM tries its best to produce something good. To do so it has to reason about the switch cases values at compile time, hence the LLVM error.
We could lower this kind of switch using a chain of if/else if this turns out to be a supported use case.
Huh. I suppose the recent LTO trend blurs the line between compile and link time, only adding to my confusion. I definitely see the issue if compilation and linking are considered two separate steps, which would force the compiler in this case to generate non-optimal code, as well as adhere to some convention the linker understands to satisfy the semantics of the switch statement.
At least in my C code I accomplish this by switching on an enum and then calling the function that enum refers to, which is already straight forwardly doable in Zig.
Interesting.
I can resort to an if-else chain; but aesthetically a switch is more desirable.
I am obviously not at all clear on the semantics of switch
and have been making do.
FYI, this code compiles and works:
const std = @import("std");
const Dispatch = struct {
op: fn() void = undefined,
};
fn A() void {
std.debug.warn("A\n", .{});
}
fn B() void {
std.debug.warn("B\n", .{});
}
fn C() void {
std.debug.warn("C\n", .{});
}
fn D() void {
std.debug.warn("D\n", .{});
}
pub fn main() void {
var dispatch = Dispatch{ .op = A };
switch (dispatch.op) {
A => A(),
B => B(),
C => C(),
else => unreachable,
}
}
@GrooveStomp On Godbolt with release-fast it results in a panic when main is exported.
Added "docs" to remind to add which types a switch allows to the language specification before closing the issue.
I'll try this again when I get home, but the behavior here, even if it's not supposed to work was bad. My processor utilization spiked, the build took several seconds longer than normal before being terminated (without input) by the OS. I'll pull latest and see if this is still true; but it was happening on both 0.5.0 and master when reported here.
I've pulled master today (2020-01-18) and have reproduced this on both
master
and0.5.0
. Here's a gist with the problem program: https://gist.github.com/GrooveStomp/15d8d8b8827d59ece022b325be9c3ac6Reproduced here:
This does not build. Output with zig
0.5.0
:And with
zig (edge) 0.5.0+b72f85819 from Jay Petacat (jayschwa) refreshed
: