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

Support inferred error sets in recursion #2971

Open
hryx opened this issue Jul 29, 2019 · 2 comments
Open

Support inferred error sets in recursion #2971

hryx opened this issue Jul 29, 2019 · 2 comments
Labels
accepted This proposal is planned. contributor friendly This issue is limited in scope and/or knowledge of Zig internals. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@hryx
Copy link
Sponsor Contributor

hryx commented Jul 29, 2019

This is a proposal based on the question raised in #763. (If #763 is considered the tracking issue or the final word, please feel free to close this one -- I didn't interpret any of the comments there as conclusive.)

Thanks @rjtobin for resurfacing the issue in IRC.

Summary

If a call graph is recursive, a return type with inferred error set may trigger this compile error:

cannot resolve inferred error set 'glarf': function 'kloyp' not fully analyzed yet

If all functions in that cycle use inferred error sets, the error is guaranteed to happen.

pub fn main() void {
    f1(false) catch {};
}

fn f1(x: bool) !void { // recurses
    return if (x) error.Bad else f1(x);
}

fn f2(x: bool) !void { // recurses
    return if (x) f2(x) else error.Bad;
}

If at least one of the functions in the cycle has an inferred error set, the error may happen. Given this error set:

const E = error{Bad};

Changing f1 to return E!void prevents the error. Leaving f1 alone and instead changing f2 to return E!void does not prevent the error. The outcome may be deterministic or it may be based on the color of the giant spaghetti monster's mood ring, I dunno.

Proposal

Guarantee that inferred error sets are allowed even in cyclic call graphs.

Alternatives

Explicitly state that recursion is incompatible with inferred error sets. "Wait!" I hear you cry, "the documentation already says exactly that". It sure does, but it is also acknowledges that this limitation may be removed in the future. We just need to decide (eventually) whether to add support or officially make it unsupported for the language specification (#75).

Note: Currently, I am neutral on this enhancement. It's not blocking me. This issue is just meant to track it and aggregate potential use cases.

@andrewrk
Copy link
Member

This is implemented and working in self-hosted, only thing left to close the issue is ensure we have behavior test coverage.

@andrewrk andrewrk modified the milestones: 0.10.0, 0.10.1 Aug 24, 2022
@andrewrk andrewrk added the contributor friendly This issue is limited in scope and/or knowledge of Zig internals. label Aug 24, 2022
@andrewrk andrewrk modified the milestones: 0.10.1, 0.11.0 Jan 10, 2023
@andrewrk andrewrk modified the milestones: 0.11.0, 0.12.0 Apr 9, 2023
@mlugg
Copy link
Member

mlugg commented May 5, 2023

Note that this works for plain recursion, but not mutual recursion:

fn f() !void {
    try g(false);
}

fn g(b: bool) !void {
    if (b) {
        try f();
    } else {
        return error.Foo;
    }
}

comptime {
    _ = f; // or g
}
thing.zig:7:14: error: unable to resolve inferred error set
        try f();
            ~^~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. contributor friendly This issue is limited in scope and/or knowledge of Zig internals. 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

3 participants