Skip to content

Recursive function definitions do not compile while equivalent structs do. #1114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jaccarmac opened this issue Jun 15, 2018 · 2 comments
Closed
Labels
bug Observed behavior contradicts documented or intended behavior
Milestone

Comments

@jaccarmac
Copy link

Perhaps I'm missing something w.r.t. the semantics of what I'm doing or with the design of the compiler, but I did some playing with this issue and can't understand the asymmetry.

Context: I'm working on a lexer based on the design of the lexer in Rob Pike's talk "Lexical Scanning in Go". One of the keys to the lexer implementation is this function type definition. Naively translated to Zig it looks like this:

const StateFn = fn(lexer: *Lexer) StateFn;

That fails to compile because StateFn depends on itself, as expected. However, after some digging into recursive structs I find that structs can contain pointers to instances of themselves if annotated correctly.

const StateFn = fn(lexer: *Lexer) ?*const StateFn;

Still won't get accepted by the compiler. So I keep digging and eventually find I can define a struct as follows:

const StateFn = struct {
    f: fn(lexer: *Lexer) ?*const StateFn,
};

This will compile. Interestingly removing the optional specifier from the return type will cause the compiler to segfault but that seems to be related to another bug, just an interesting hiccup I noticed. In any case, inside the struct I can define functions to the tune of:

...

pub fn defaultState(lexer: *Lexer) ?*const StateFn {
    comptime { return StateFn{ .f = defaultState }; }
}

The comptime wrapping is to satisfy some of my paranoia about senseless allocations.

As I understand it, all that's happening in this code is the passing of function pointers, which is what I would be looking to do with the simpler code as well. Perhaps I'm missing something subtle in type checking or elsewhere. But it would be really nice to support the simpler form and I'm eager to submit a patch and imagine I could with a little guidance w.r.t. both the language and compiler design.

@andrewrk andrewrk added this to the 0.3.0 milestone Jun 15, 2018
@andrewrk andrewrk added the bug Observed behavior contradicts documented or intended behavior label Jun 15, 2018
@andrewrk andrewrk modified the milestones: 0.3.0, 0.4.0 Sep 3, 2018
@andrewrk
Copy link
Member

andrewrk commented Apr 6, 2019

Proposal to fix this: #2174

@andrewrk
Copy link
Member

Fixed by #2174

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

2 participants