zig
zig copied to clipboard
Writing to nested slice in a function breaks initialization in certain scopes
Minimal repro:
const std = @import("std");
pub fn makeArray() [4]u8 {
var result = std.mem.zeroes([4]u8);
std.mem.writeIntBig(u32, result[0..][0..4], 0xabcdabcd);
return result;
}
const x = makeArray();
pub fn main() !void {
std.debug.print("{}\n", .{std.fmt.fmtSliceHexLower(&x)});
const y = makeArray();
std.debug.print("{}\n", .{std.fmt.fmtSliceHexLower(&y)});
}
This prints:
00000000
abcdabcd
but I think it should print abcdabcd
on both lines.
The issue seems to be caused by comptime slices:
pub fn makeArray1() [4]u8 {
var result = std.mem.zeroes([4]u8);
std.mem.writeIntBig(u32, result[0..4], 0xabcdabcd);
return result;
}
pub fn makeArray2() [4]u8 {
var result = std.mem.zeroes([4]u8);
std.mem.writeIntBig(u32, &result, 0xabcdabcd);
return result;
}
pub fn main() !void {
const arr1 = comptime makeArray1();
std.debug.print("makeArray1: {}\n", .{std.fmt.fmtSliceHexLower(&arr1)});
const arr2 = comptime makeArray2();
std.debug.print("makeArray2: {}\n", .{std.fmt.fmtSliceHexLower(&arr2)});
}
makeArray1: 00000000
makeArray2: abcdabcd
Stage2 fixed the original test case but it still behaves incorrectly for other inputs, here's an updated test case:
const std = @import("std");
pub fn makeArray() [16]u8 {
var result = std.mem.zeroes([16]u8);
std.mem.writeIntBig(u32, result[0..][0..4], 0xabcdabcd);
std.mem.writeIntBig(u32, result[4..][0..4], 0xabcdabcd);
std.mem.writeIntBig(u32, result[8..][0..4], 0xabcdabcd);
std.mem.writeIntBig(u32, result[12..][0..4], 0xabcdabcd);
return result;
}
const x = makeArray();
pub fn main() !void {
std.debug.print("{}\n", .{std.fmt.fmtSliceHexLower(&x)});
const y = makeArray();
std.debug.print("{}\n", .{std.fmt.fmtSliceHexLower(&y)});
}
Output:
abcdabcdab000000ab000000ab000000
abcdabcdabcdabcdabcdabcdabcdabcd
zig version 0.10.0-dev.3952+9e070b653
We can create a test/behavior/bugs/8304.zig
with
const std = @import("std");
fn makeArray1() [4]u8 {
var result = std.mem.zeroes([4]u8);
std.mem.writeIntBig(u32, result[0..][0..4], 0xabcdabcd);
return result;
}
const x1 = makeArray1();
test {
const y1 = makeArray2();
std.testing.expectEqualStrings(std.fmt.fmtSliceHexLower(&x1), std.fmt.fmtSliceHexLower(&y1));
}
fn makeArray2() [16]u8 {
var result = std.mem.zeroes([16]u8);
std.mem.writeIntBig(u32, result[0..][0..4], 0xabcdabcd);
std.mem.writeIntBig(u32, result[4..][0..4], 0xabcdabcd);
std.mem.writeIntBig(u32, result[8..][0..4], 0xabcdabcd);
std.mem.writeIntBig(u32, result[12..][0..4], 0xabcdabcd);
return result;
}
const x2 = makeArray2();
test {
const y2 = makeArray2();
std.testing.expectEqualStrings(std.fmt.fmtSliceHexLower(&x2), std.fmt.fmtSliceHexLower(&y2));
}
when this is fixed.