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(...@@ -29684,6 +29684,7 @@ fn storePtrVal(
29684 try sema.checkComptimeVarStore(block, src, mut_kit.mut_decl);29684 try sema.checkComptimeVarStore(block, src, mut_kit.mut_decl);
2968529685
29686 switch (mut_kit.pointee) {29686 switch (mut_kit.pointee) {
29687 .opv => {},
29687 .direct => |val_ptr| {29688 .direct => |val_ptr| {
29688 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {29689 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {
29689 val_ptr.* = (try val_ptr.intern(operand_ty, mod)).toValue();29690 val_ptr.* = (try val_ptr.intern(operand_ty, mod)).toValue();
...@@ -29741,6 +29742,7 @@ fn storePtrVal(...@@ -29741,6 +29742,7 @@ fn storePtrVal(
29741const ComptimePtrMutationKit = struct {29742const ComptimePtrMutationKit = struct {
29742 mut_decl: InternPool.Key.Ptr.Addr.MutDecl,29743 mut_decl: InternPool.Key.Ptr.Addr.MutDecl,
29743 pointee: union(enum) {29744 pointee: union(enum) {
29745 opv,
29744 /// The pointer type matches the actual comptime Value so a direct29746 /// The pointer type matches the actual comptime Value so a direct
29745 /// modification is possible.29747 /// modification is possible.
29746 direct: *Value,29748 direct: *Value,
...@@ -29793,6 +29795,7 @@ fn beginComptimePtrMutation(...@@ -29793,6 +29795,7 @@ fn beginComptimePtrMutation(
29793 const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod);29795 const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod);
29794 var parent = try sema.beginComptimePtrMutation(block, src, eu_ptr.toValue(), eu_ty);29796 var parent = try sema.beginComptimePtrMutation(block, src, eu_ptr.toValue(), eu_ty);
29795 switch (parent.pointee) {29797 switch (parent.pointee) {
29798 .opv => unreachable,
29796 .direct => |val_ptr| {29799 .direct => |val_ptr| {
29797 const payload_ty = parent.ty.errorUnionPayload(mod);29800 const payload_ty = parent.ty.errorUnionPayload(mod);
29798 if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) {29801 if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) {
...@@ -29835,6 +29838,7 @@ fn beginComptimePtrMutation(...@@ -29835,6 +29838,7 @@ fn beginComptimePtrMutation(
29835 const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod);29838 const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod);
29836 var parent = try sema.beginComptimePtrMutation(block, src, opt_ptr.toValue(), opt_ty);29839 var parent = try sema.beginComptimePtrMutation(block, src, opt_ptr.toValue(), opt_ty);
29837 switch (parent.pointee) {29840 switch (parent.pointee) {
29841 .opv => unreachable,
29838 .direct => |val_ptr| {29842 .direct => |val_ptr| {
29839 const payload_ty = parent.ty.optionalChild(mod);29843 const payload_ty = parent.ty.optionalChild(mod);
29840 switch (val_ptr.ip_index) {29844 switch (val_ptr.ip_index) {
...@@ -29888,16 +29892,30 @@ fn beginComptimePtrMutation(...@@ -29888,16 +29892,30 @@ fn beginComptimePtrMutation(
29888 var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.base.toValue(), base_elem_ty);29892 var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.base.toValue(), base_elem_ty);
2988929893
29890 switch (parent.pointee) {29894 switch (parent.pointee) {
29895 .opv => unreachable,
29891 .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) {29896 .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) {
29892 .Array, .Vector => {29897 .Array, .Vector => {
29898 const elem_ty = parent.ty.childType(mod);
29893 const check_len = parent.ty.arrayLenIncludingSentinel(mod);29899 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 }
29894 if (elem_ptr.index >= check_len) {29913 if (elem_ptr.index >= check_len) {
29895 // TODO have the parent include the decl so we can say "declared here"29914 // TODO have the parent include the decl so we can say "declared here"
29896 return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{29915 return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{
29897 elem_ptr.index, check_len,29916 elem_ptr.index, check_len,
29898 });29917 });
29899 }29918 }
29900 const elem_ty = parent.ty.childType(mod);
2990129919
29902 // We might have a pointer to multiple elements of the array (e.g. a pointer29920 // We might have a pointer to multiple elements of the array (e.g. a pointer
29903 // to a sub-array). In this case, we just have to reinterpret the relevant29921 // to a sub-array). In this case, we just have to reinterpret the relevant
...@@ -30072,6 +30090,7 @@ fn beginComptimePtrMutation(...@@ -30072,6 +30090,7 @@ fn beginComptimePtrMutation(
3007230090
30073 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty);30091 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty);
30074 switch (parent.pointee) {30092 switch (parent.pointee) {
30093 .opv => unreachable,
30075 .direct => |val_ptr| switch (val_ptr.ip_index) {30094 .direct => |val_ptr| switch (val_ptr.ip_index) {
30076 .empty_struct => {30095 .empty_struct => {
30077 const duped = try sema.arena.create(Value);30096 const duped = try sema.arena.create(Value);
test/behavior/comptime_memory.zig+8
...@@ -451,3 +451,11 @@ test "type pun null pointer-like optional" {...@@ -451,3 +451,11 @@ test "type pun null pointer-like optional" {
451 // note that expectEqual hides the bug451 // note that expectEqual hides the bug
452 try testing.expect(@as(*const ?*i8, @ptrCast(&p)).* == null);452 try testing.expect(@as(*const ?*i8, @ptrCast(&p)).* == null);
453}453}
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}