Commit f803761e13

John Schmidt <john.schmidt.h@gmail.com>
2024-02-11 22:55:13
Fix tuple default values
- Add default values to the list of comptime-known elements in `zirValidatePtrArrayInit` - In `structFieldValueComptime`, only assert `haveFieldInits` if we enter the`fieldIsComptime` branch (otherwise they are not needed).
1 parent 7a045ed
Changed files (3)
src
test
behavior
src/Sema.zig
@@ -5043,22 +5043,33 @@ fn zirValidatePtrArrayInit(
     const array_ty = sema.typeOf(array_ptr).childType(mod).optEuBaseType(mod);
     const array_len = array_ty.arrayLen(mod);
 
+    // Collect the comptime element values in case the array literal ends up
+    // being comptime-known.
+    const element_vals = try sema.arena.alloc(
+        InternPool.Index,
+        try sema.usizeCast(block, init_src, array_len),
+    );
+
     if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) {
         .Struct => {
             var root_msg: ?*Module.ErrorMsg = null;
             errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
 
+            try sema.resolveStructFieldInits(array_ty);
             var i = instrs.len;
             while (i < array_len) : (i += 1) {
-                const default_val = array_ty.structFieldDefaultValue(i, mod);
-                if (default_val.toIntern() == .unreachable_value) {
+                const default_val = array_ty.structFieldDefaultValue(i, mod).toIntern();
+                if (default_val == .unreachable_value) {
                     const template = "missing tuple field with index {d}";
                     if (root_msg) |msg| {
                         try sema.errNote(block, init_src, msg, template, .{i});
                     } else {
                         root_msg = try sema.errMsg(block, init_src, template, .{i});
                     }
+                    continue;
                 }
+
+                element_vals[i] = default_val;
             }
 
             if (root_msg) |msg| {
@@ -5105,12 +5116,6 @@ fn zirValidatePtrArrayInit(
     var array_is_comptime = true;
     var first_block_index = block.instructions.items.len;
 
-    // Collect the comptime element values in case the array literal ends up
-    // being comptime-known.
-    const element_vals = try sema.arena.alloc(
-        InternPool.Index,
-        try sema.usizeCast(block, init_src, array_len),
-    );
     const air_tags = sema.air_instructions.items(.tag);
     const air_datas = sema.air_instructions.items(.data);
 
src/type.zig
@@ -3073,8 +3073,8 @@ pub const Type = struct {
         const ip = &mod.intern_pool;
         switch (ip.indexToKey(ty.toIntern())) {
             .struct_type => |struct_type| {
-                assert(struct_type.haveFieldInits(ip));
                 if (struct_type.fieldIsComptime(ip, index)) {
+                    assert(struct_type.haveFieldInits(ip));
                     return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
                 } else {
                     return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(mod);
test/behavior/tuple.zig
@@ -560,3 +560,17 @@ test "comptime fields in tuple can be initialized" {
     var a: T = .{ 0, 0 };
     _ = &a;
 }
+
+test "tuple default values" {
+    const T = struct {
+        usize,
+        usize = 123,
+        usize = 456,
+    };
+
+    const t: T = .{1};
+
+    try expectEqual(1, t[0]);
+    try expectEqual(123, t[1]);
+    try expectEqual(456, t[2]);
+}