-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
implement multi-object for loops #14671
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
Conversation
2689f80
to
844325a
Compare
Is |
I assume the "count up forever" example |
Does this support or is it going to support |
In a similar way of the indexed part select of Verilog one could define a count up with |
How would I make my structs working with
And how to loop over with lazy / infinite iterators which don't have known size? |
@likern use |
If so I don't think it makes sense to support counting down by flipping the numbers. Usually when counting down you want an inclusive endpoint. I'm not sure that reverse iteration is common enough to warrant special language support, but if it is, it would be nice if it were done in a way that could work on arrays and slices too. e.g. |
Possibly missing a test case for const thing: [*]const u8 = @as([]const u8, "abcdef").ptr;
for (thing, 0..6) |v, i| { ... } |
4b45a6e
to
85a5f01
Compare
I think I personally prefer the readability of |
d72a927
to
b7f9f9f
Compare
You are obviously very good at sports. |
* Allow unbounded looping. * Lower by incrementing raw pointers for each iterable rather than incrementing a single index variable. This elides safety checks without any analysis required thanks to the length assertion and lowers to decent machine code even in debug builds. - An "end" value is selected, prioritizing a counter if possible, falling back to a runtime calculation of ptr+len on a slice input. * Specialize on the pattern `0..`, avoiding an unnecessary subtraction instruction being emitted. * Add the `for_check_lens` ZIR instruction.
This strategy uses pointer arithmetic to iterate through the loop. This has a problem, however, which is tuples. AstGen does not know whether a given indexable is a tuple or can be iterated based on contiguous memory. Tuples unlike other indexables cannot be represented as a many-item pointer that is incremented as the loop counter. So, after this commit, I will modify AstGen back closer to how @Vexu had it before, using a counter and array element access.
The intent here is to revert this commit after Zig 0.10.0 is released.
This also makes another breaking change to for loops: in order to capture a pointer of an element, one must take the address of array values. This simplifies a lot of things, and makes more sense than how it was before semantically. It is still legal to use a for loop on an array value if the corresponding element capture is byval instead of byref.
One of the main points of for loops is that you can safety check the length once, before entering the loop, and then safely assume that every element inside the loop is in bounds. In master branch, the safety checks are incorrectly intact even inside for loops. This commit fixes it. It's especially nice with multi-object loops because the number of elided checks is N * M where N is how many iterations and M is how many objects.
Since for loops are statically analyzed to have an upper bound, and the loop counter is a usize, it is impossible for it to overflow.
5866c47
to
5fc6bbe
Compare
The latent bug in
Note that instructions |
🎉🎉🎉 |
This exposed a latent bug in the (experimental) x86 backend but I'm not letting it block the merge of this PR, since all the other backends are fine.
Closes #7257.
merge checklist:
Release Notes
There are two patterns to update here. The first one can be auto-update by
zig fmt
, but if you forget to runzig fmt
you will see the error:The fix is to add a counter corresponding to the index like this:
The second one must be done manually. It occurs when you try to capture a by-value array element by-ref:
If you see this, the solution is simple, just add a
&
in front of the array input to the for loop: