authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-31 04:26:27-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-31 21:37:35-04:00
log50cdb65784937965b5871037ff40bc34d8eb14af
tree34982d90a90a389644d9808676ecdb8419ff76b3
parent46062f1c13d8ee9eebf49806660c2271f2acc613

Sema: fix incorrect error comptime-mutating empty array


2 files changed, 28 insertions(+), 1 deletions(-)

src/Sema.zig+20-1
......@@ -29684,6 +29684,7 @@ fn storePtrVal(
2968429684 try sema.checkComptimeVarStore(block, src, mut_kit.mut_decl);
2968529685
2968629686 switch (mut_kit.pointee) {
29687 .opv => {},
2968729688 .direct => |val_ptr| {
2968829689 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {
2968929690 val_ptr.* = (try val_ptr.intern(operand_ty, mod)).toValue();
......@@ -29741,6 +29742,7 @@ fn storePtrVal(
2974129742const ComptimePtrMutationKit = struct {
2974229743 mut_decl: InternPool.Key.Ptr.Addr.MutDecl,
2974329744 pointee: union(enum) {
29745 opv,
2974429746 /// The pointer type matches the actual comptime Value so a direct
2974529747 /// modification is possible.
2974629748 direct: *Value,
......@@ -29793,6 +29795,7 @@ fn beginComptimePtrMutation(
2979329795 const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod);
2979429796 var parent = try sema.beginComptimePtrMutation(block, src, eu_ptr.toValue(), eu_ty);
2979529797 switch (parent.pointee) {
29798 .opv => unreachable,
2979629799 .direct => |val_ptr| {
2979729800 const payload_ty = parent.ty.errorUnionPayload(mod);
2979829801 if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) {
......@@ -29835,6 +29838,7 @@ fn beginComptimePtrMutation(
2983529838 const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod);
2983629839 var parent = try sema.beginComptimePtrMutation(block, src, opt_ptr.toValue(), opt_ty);
2983729840 switch (parent.pointee) {
29841 .opv => unreachable,
2983829842 .direct => |val_ptr| {
2983929843 const payload_ty = parent.ty.optionalChild(mod);
2984029844 switch (val_ptr.ip_index) {
......@@ -29888,16 +29892,30 @@ fn beginComptimePtrMutation(
2988829892 var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.base.toValue(), base_elem_ty);
2988929893
2989029894 switch (parent.pointee) {
29895 .opv => unreachable,
2989129896 .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) {
2989229897 .Array, .Vector => {
29898 const elem_ty = parent.ty.childType(mod);
2989329899 const check_len = parent.ty.arrayLenIncludingSentinel(mod);
29900 if ((try sema.typeHasOnePossibleValue(ptr_elem_ty)) != null) {
29901 if (elem_ptr.index > check_len) {
29902 // TODO have the parent include the decl so we can say "declared here"
29903 return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{
29904 elem_ptr.index, check_len,
29905 });
29906 }
29907 return .{
29908 .mut_decl = parent.mut_decl,
29909 .pointee = .opv,
29910 .ty = elem_ty,
29911 };
29912 }
2989429913 if (elem_ptr.index >= check_len) {
2989529914 // TODO have the parent include the decl so we can say "declared here"
2989629915 return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{
2989729916 elem_ptr.index, check_len,
2989829917 });
2989929918 }
29900 const elem_ty = parent.ty.childType(mod);
2990129919
2990229920 // We might have a pointer to multiple elements of the array (e.g. a pointer
2990329921 // to a sub-array). In this case, we just have to reinterpret the relevant
......@@ -30072,6 +30090,7 @@ fn beginComptimePtrMutation(
3007230090
3007330091 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty);
3007430092 switch (parent.pointee) {
30093 .opv => unreachable,
3007530094 .direct => |val_ptr| switch (val_ptr.ip_index) {
3007630095 .empty_struct => {
3007730096 const duped = try sema.arena.create(Value);
test/behavior/comptime_memory.zig+8
......@@ -451,3 +451,11 @@ test "type pun null pointer-like optional" {
451451 // note that expectEqual hides the bug
452452 try testing.expect(@as(*const ?*i8, @ptrCast(&p)).* == null);
453453}
454
455test "write empty array to end" {
456 comptime var array: [5]u8 = "hello".*;
457 array[5..5].* = .{};
458 array[5..5].* = [0]u8{};
459 array[5..5].* = [_]u8{};
460 try testing.expectEqualStrings("hello", &array);
461}