implement multi-object for loops by andrewrk · Pull Request #14671 · ziglang/zig

2 min read Original article ↗

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:

  • implement multi-object for loops
  • make zig fmt automatically upgrade old code
  • add parser_test.zig test case for zig fmt upgrading the old code
  • improve compile error messages
  • omit OOB safety checks of for loop captures (master branch incorrectly has these)
  • update existing behavior tests to new syntax and get them passing
  • make unbounded looping illegal
  • update stage1.wasm
  • omit safety check for incrementing for loop counter
  • implement all the test cases
  • update the language reference

Release Notes

There are two patterns to update here. The first one can be auto-update by zig fmt, but if you forget to run zig fmt you will see the error:

/home/andy/dev/zig/lib/std/crypto/hmac.zig:49:36: error: extra capture in for loop
            for (ctx.o_key_pad) |*b, i| {
                                   ^
/home/andy/dev/zig/lib/std/crypto/hmac.zig:49:36: note: run 'zig fmt' to upgrade your code automatically

The fix is to add a counter corresponding to the index like this:

--- a/lib/std/crypto/hmac.zig
+++ b/lib/std/crypto/hmac.zig
@@ -46,11 +46,11 @@ pub fn Hmac(comptime Hash: type) type {
                 mem.copy(u8, scratch[0..], key);
             }
 
-            for (ctx.o_key_pad) |*b, i| {
+            for (ctx.o_key_pad, 0..) |*b, i| {
                 b.* = scratch[i] ^ 0x5c;
             }

The second one must be done manually. It occurs when you try to capture a by-value array element by-ref:

/home/andy/dev/zig/lib/std/crypto/hmac.zig:49:21: error: pointer capture of non pointer type '[64]u8'
            for (ctx.o_key_pad, 0..) |*b, i| {
                 ~~~^~~~~~~~~~

If you see this, the solution is simple, just add a & in front of the array input to the for loop:

--- a/lib/std/crypto/hmac.zig
+++ b/lib/std/crypto/hmac.zig
@@ -46,11 +46,11 @@ pub fn Hmac(comptime Hash: type) type {
                 mem.copy(u8, scratch[0..], key);
             }
 
-            for (ctx.o_key_pad) |*b, i| {
+            for (&ctx.o_key_pad, 0..) |*b, i| {
                 b.* = scratch[i] ^ 0x5c;
             }