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

Proposal: Per-scope comptime branch quota #7407

Open
ghost opened this issue Dec 12, 2020 · 0 comments
Open

Proposal: Per-scope comptime branch quota #7407

ghost opened this issue Dec 12, 2020 · 0 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@ghost
Copy link

ghost commented Dec 12, 2020

Originally part of #5895, but was effectively a separate concept even before #7396 was accepted. Now splitting.

Currently, there is a single global branch quota per context that cannot be read. This has two problems.

Firstly, an irresponsible author of a long-running calculation may, instead of reasoning about its behaviour, choose to simply increment the quota in a loop, bypassing the purpose of a quota altogether:

comptime var q = 1001;
inline while (some_condition) : (q += 1) {
    @setEvalBranchQuota(q);
    // As long as no more than 1000 branches have already been taken,
    // whatever follows is guaranteed to never exceed the quota
}

Secondly, a responsible author who wishes to increase the quota must take a blind guess as to how many branches have already been taken:

// Say we expect the loop to take up to 500 iterations
// -- we wish to add 500 to the quota to guarantee success
@setEvalBranchQuota(1500); // No good;
// the quota has already been increased to 2000,
// and 1900 branches have been taken
inline while (some_condition) {
    // After 100 iterations, compilation fails
}

Allowing the quota to be read solves the second problem but worsens the first; restricting @setEvalBranchQuota to global scope solves the first but worsens the second.

I propose that we abolish @setEvalBranchQuota entirely, in favour of a new builtin: @addBranchQuota(comptime q: int) void. This may only be called within linear scope. It imbues the scope with a branch quota of its own initialised to q, counted separately from the global quota, and only valid within that scope. A branch first draws from its own scope's quota, then when that is exhausted (or if it does not exist) it draws from the enclosing linear scope's quota if applicable, then from the calling function's quota, and so on up the call stack until it reaches the context quota.

The following actions incur a branch debt:

  • Repeating a while loop
  • Function recursion
  • Inline expansion recursion

These are the only actions which could potentially loop infinitely -- note especially that for loops are not included, as they iterate up to a fixed number of times. A loop repeat is debted to the scope containing the loop, and a function or inline expansion recursion to the scope of the topmost instance -- otherwise a badly behaving function could increment its own quota to infinity by some means. If the compiler decides to pre-compute values not explicitly marked as comptime, or inlines non-inline functions or loops, the mechanism for bounding these actions is internal to the compiler and separate from the local quota -- it would be unfair and unpredictable to do otherwise.

Increasing the context quota cannot be done from within the program -- it requires a command line option, say -Dbranch-quota=2000 or something similar; the lack of distinction between top-level and lower level nonlinear scope makes it possible to indirectly loop-increment the surrounding quota otherwise.

@Vexu Vexu added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Dec 12, 2020
@Vexu Vexu added this to the 0.8.0 milestone Dec 12, 2020
@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 May 19, 2021
@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 Nov 23, 2021
@andrewrk andrewrk modified the milestones: 0.10.0, 0.11.0 Apr 16, 2022
@andrewrk andrewrk modified the milestones: 0.11.0, 0.12.0 Apr 9, 2023
@andrewrk andrewrk modified the milestones: 0.13.0, 0.12.0 Jul 9, 2023
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

2 participants