zig icon indicating copy to clipboard operation
zig copied to clipboard

Writing to nested slice in a function breaks initialization in certain scopes

Open jcmoyer opened this issue 3 years ago • 2 comments

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.

jcmoyer avatar Mar 20 '21 09:03 jcmoyer

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

Vexu avatar Mar 20 '21 18:03 Vexu

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

jcmoyer avatar Aug 26 '22 12:08 jcmoyer

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.

wooster0 avatar Dec 07 '22 19:12 wooster0