diff options
| -rw-r--r-- | src/Sema.zig | 17 | ||||
| -rw-r--r-- | test/behavior/array.zig | 27 | ||||
| -rw-r--r-- | test/behavior/comptime_memory.zig | 8 |
3 files changed, 42 insertions, 10 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index e6652a5d66..8b6c269246 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -26648,6 +26648,23 @@ fn beginComptimePtrMutation( }); } const elem_ty = parent.ty.childType(); + + // We might have a pointer to multiple elements of the array (e.g. a pointer + // to a sub-array). In this case, we just have to reinterpret the relevant + // bytes of the whole array rather than any single element. + const elem_abi_size_u64 = try sema.typeAbiSize(elem_ptr.elem_ty); + if (elem_abi_size_u64 < try sema.typeAbiSize(ptr_elem_ty)) { + const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); + return .{ + .decl_ref_mut = parent.decl_ref_mut, + .pointee = .{ .reinterpret = .{ + .val_ptr = val_ptr, + .byte_offset = elem_abi_size * elem_ptr.index, + } }, + .ty = parent.ty, + }; + } + switch (val_ptr.tag()) { .undef => { // An array has been initialized to undefined at comptime and now we diff --git a/test/behavior/array.zig b/test/behavior/array.zig index a5ecd6f115..3d711357f3 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -48,16 +48,23 @@ fn getArrayLen(a: []const u32) usize { test "array concat with undefined" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - { - var array = "hello".* ++ @as([5]u8, undefined); - array[5..10].* = "world".*; - try std.testing.expect(std.mem.eql(u8, &array, "helloworld")); - } - { - var array = @as([5]u8, undefined) ++ "world".*; - array[0..5].* = "hello".*; - try std.testing.expect(std.mem.eql(u8, &array, "helloworld")); - } + const S = struct { + fn doTheTest() !void { + { + var array = "hello".* ++ @as([5]u8, undefined); + array[5..10].* = "world".*; + try std.testing.expect(std.mem.eql(u8, &array, "helloworld")); + } + { + var array = @as([5]u8, undefined) ++ "world".*; + array[0..5].* = "hello".*; + try std.testing.expect(std.mem.eql(u8, &array, "helloworld")); + } + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); } test "array concat with tuple" { diff --git a/test/behavior/comptime_memory.zig b/test/behavior/comptime_memory.zig index a4f9f2f7a9..71d177395b 100644 --- a/test/behavior/comptime_memory.zig +++ b/test/behavior/comptime_memory.zig @@ -412,3 +412,11 @@ test "bitcast packed union to integer" { try testing.expectEqual(@as(u2, 2), cast_b); } } + +test "mutate entire slice at comptime" { + comptime { + var buf: [3]u8 = undefined; + const x: [2]u8 = .{ 1, 2 }; // Avoid RLS + buf[1..3].* = x; + } +} |
