Skip to content
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

compiler awareness of reachable functions, function reachability analysis #4094

Closed
andrewrk opened this issue Jan 7, 2020 · 1 comment
Closed
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Jan 7, 2020

Reaching unreachable is Illegal Behavior (#2402). If the compiler can prove that this happens at compile time, then it can be a compile error, which is strongly preferred to a runtime check, or worse, Undefined Behavior.

Unfortunately, the compiler is unable to detect some obvious cases when it should be a compile error. For example:

pub fn main() void {
    unreachable;
}

This should be a compile error. It is understood that main is reachable, and therefore control flow is guaranteed to unconditionally reach unreachable. Another example:

pub fn main() void {
    foo();
}
fn foo() void {
    unreachable;
}

In this case it should also be a compile error. foo() basically is equivalent to unreachable in this case.

pub fn main() void {
    if (args.len != 10) foo();
}
fn foo() void {
    unreachable;
}

Now it should not be a compile error. unreachable is no longer guaranteed to be hit. You can get the idea here that the call graph will quickly lose the ability to prove that functions are unconditionally reachable. So to take advantage of this it may be necessary to annotate that functions are reachable. Or maybe have some kind of rule that all functions must be reachable, unless otherwise specified.

This proposal is vague because it's not clear how to go about solving this problem yet.

Where this starts to be important is with #425. Example:

pub fn assert(ok: bool) void {
    if (!ok) unreachable; // assertion failure
}

The use case I have here is when using assert with a comptime known parameter:

assert(x > y);

Assuming x > y happens to be a comptime-known value, #425 would change this into:

unreachable;

It would be really, really beneficial if this could turn into a compile-error. Implicit compile-time asserts. But this unreachable can only be reported as a compile error if zig can prove that the unreachable is unconditionally reachable.

So unless this proposal can be implemented, we are left with explicit compile-time asserts:

comptime assert(x > y);
@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Jan 7, 2020
@andrewrk andrewrk added this to the 0.7.0 milestone Jan 7, 2020
@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Oct 27, 2020
@andrewrk
Copy link
Member Author

So to take advantage of this it may be necessary to annotate that functions are reachable. Or maybe have some kind of rule that all functions must be reachable, unless otherwise specified.

This proposal is vague because it's not clear how to go about solving this problem yet.

After putting some thought into this, I don't have a coherent and detailed proposal for how to annotate reachability or how to specify the concept of reachability in the language specification. Without a more clear, detailed, and complete proposal, there is nothing to do here. Current path forward will be to accept the null hypothesis of keeping the language simple: code paths are only runtime-known whether they are reachable or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

1 participant