Wierd differnce between Vector and array on 0.17.0

While trying to make a version of Cubyz that works with zig 0.17.0 (master) I got very weird graphical artifacts and could track it down to this reproduce:

const std = @import("std");

pub fn glCall(a: [*c]c_int) void {
    a[0] = 0;
}

pub fn  main() !void {
    var resultArr: [2]i32 = undefined;
    glCall(&resultArr[0]);
    glCall(&resultArr[1]);
    std.debug.print("resultArr: {any}\n", .{resultArr});
    
    var resultVec: @Vector(2, i32) = undefined;
    glCall(&resultVec[0]);
    glCall(&resultVec[1]);
    std.debug.print("resultVec: {any}\n", .{resultVec});
}

(code is heavly inspired by the actual code, maybe there is a better reproduce)
Output:

resultArr: { 0, 0 }
resultVec: { 0, -1431655766 }

This seems like a bug, but maybe I just missed some breaking change?

Maybe to clarify. with 0.16.0 the array and the vector variant have the same output

You seem to be on to something. Zig 0.17 only calls glCall 3 times rather than 4..

I removed the std.debug.print() to get the reproduction case to be tiny.

1 Like

The compiler bug here is that this code shouldn’t compile! Vectors are allowed to have weird non-byte-aligned layouts, so pointers to their elements have special types which aren’t meant to be compatible with normal pointer types, such as your [*c]c_int. Would you mind opening an issue on the Zig repository? EDIT: actually, I just filed it myself, as #36378.

By the way, never use [*c]T types in your own code! C pointer types exist only to be generated by translate-c. When writing code manually, it can and should always be replaced with a more specific pointer type, usually either *T or [*]T.

8 Likes

Ah that makes sense.
And no worries glCall was just supposed to mimic a function generated by translateC which is in the actual code used.

2 Likes

I’d assumed it was an OpenGL function with that name.

3 Likes

You caught me

Think it’s been fixed.

https://codeberg.org/ziglang/zig/pulls/36097