| author | |
| committer | |
| log | badf016b83583df98ac9c56e4147235fb9bd7f8c |
| tree | 423f4ff5e0704c57e178ec441c906b30aaa98b78 |
| parent | 3c0e8b34d76d7c081a5d8b1f2d060fe6735e8d12 |
Without including the sentinel in this check, a sentinel terminated array with repeated elements up to the sentinel would get interned as a repeated aggregate, meaning that when the value would get uninterned for mutation, all values including the sentinel would get set to the repeated element, even though the sentinel is *not* repeated.
Without this fix, `x.a[2]` in the added test case would end up with the value 50.
Closes #373392 files changed, 13 insertions(+), 1 deletions(-)
src/InternPool.zig+1-1| ... | ... | @@ -7901,7 +7901,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 7901 | 7901 | switch (aggregate.storage) { |
| 7902 | 7902 | .bytes => |bytes| for (bytes.toSlice(len, ip)[1..]) |byte| |
| 7903 | 7903 | if (byte != bytes.at(0, ip)) break :repeated, |
| 7904 | .elems => |elems| for (elems[1..@intCast(len)]) |elem| | |
| 7904 | .elems => |elems| for (elems[1..@intCast(len_including_sentinel)]) |elem| | |
| 7905 | 7905 | if (elem != elems[0]) break :repeated, |
| 7906 | 7906 | .repeated_elem => {}, |
| 7907 | 7907 | } |
test/behavior/comptime_memory.zig+12| ... | ... | @@ -606,3 +606,15 @@ test "reinterpret pointer as optional pointer via double-pointer coercion" { |
| 606 | 606 | comptime assert(@TypeOf(loaded) == ?*anyopaque); |
| 607 | 607 | comptime assert(@intFromPtr(loaded) == 0x1000); |
| 608 | 608 | } |
| 609 | ||
| 610 | test "comptime store to sentinel-terminated array in an extern struct" { | |
| 611 | comptime { | |
| 612 | var x: extern struct { | |
| 613 | a: [2:0]u8 = @splat(50), | |
| 614 | } = .{}; | |
| 615 | x.a[0] = 100; | |
| 616 | assert(x.a[0] == 100); | |
| 617 | assert(x.a[1] == 50); | |
| 618 | assert(x.a[2] == 0); | |
| 619 | } | |
| 620 | } |