I can give a specific example.

    for (0..5) |i| {
        i = i + 1;
        std.debug.print("foo {}\n", .{i});
    }
In this loop in Zig, the reassignment to i fails, because i is a constant. However, i is a new constant bound to a different value each iteration.

To potentially make it clearer that this is not mutation of a constant between iterations, technically &i could change between iterations, and the program would still be correct. This is not true with a c-style for loop using explicit mutation.