Commit 28383d4d98

WillLillis <wlillis@umass.edu>
2024-07-26 02:52:49
fix(Sema): patch segfault in `finishStructInit`
1 parent cad6530
Changed files (2)
src
test
cases
src/Sema.zig
@@ -20345,7 +20345,12 @@ fn structInitEmpty(
     defer gpa.free(field_inits);
     @memset(field_inits, .none);
 
-    return sema.finishStructInit(block, init_src, dest_src, field_inits, struct_ty, struct_ty, false);
+    // Maps field index in the struct declaration to the field index in the initialization expression.
+    const field_assign_idxs = try gpa.alloc(?usize, struct_ty.structFieldCount(zcu));
+    defer gpa.free(field_assign_idxs);
+    @memset(field_assign_idxs, null);
+
+    return sema.finishStructInit(block, init_src, dest_src, field_inits, field_assign_idxs, struct_ty, struct_ty, false);
 }
 
 fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {
@@ -20456,6 +20461,11 @@ fn zirStructInit(
         defer gpa.free(field_inits);
         @memset(field_inits, .none);
 
+        // Maps field index in the struct declaration to the field index in the initialization expression.
+        const field_assign_idxs = try gpa.alloc(?usize, resolved_ty.structFieldCount(zcu));
+        defer gpa.free(field_assign_idxs);
+        @memset(field_assign_idxs, null);
+
         var field_i: u32 = 0;
         var extra_index = extra.end;
 
@@ -20478,6 +20488,7 @@ fn zirStructInit(
             else
                 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
             assert(field_inits[field_index] == .none);
+            field_assign_idxs[field_index] = field_i;
             found_fields[field_index] = item.data.field_type;
             const uncoerced_init = try sema.resolveInst(item.data.init);
             const field_ty = resolved_ty.fieldType(field_index, zcu);
@@ -20498,7 +20509,7 @@ fn zirStructInit(
             }
         }
 
-        return sema.finishStructInit(block, src, src, field_inits, resolved_ty, result_ty, is_ref);
+        return sema.finishStructInit(block, src, src, field_inits, field_assign_idxs, resolved_ty, result_ty, is_ref);
     } else if (resolved_ty.zigTypeTag(zcu) == .@"union") {
         if (extra.data.fields_len != 1) {
             return sema.fail(block, src, "union initialization expects exactly one field", .{});
@@ -20583,6 +20594,7 @@ fn finishStructInit(
     init_src: LazySrcLoc,
     dest_src: LazySrcLoc,
     field_inits: []Air.Inst.Ref,
+    field_assign_idxs: []?usize,
     struct_ty: Type,
     result_ty: Type,
     is_ref: bool,
@@ -20684,9 +20696,9 @@ fn finishStructInit(
     }
 
     // Find which field forces the expression to be runtime, if any.
-    const opt_runtime_index = for (field_inits, 0..) |field_init, i| {
+    const opt_runtime_index = for (field_inits, field_assign_idxs) |field_init, field_assign| {
         if (!(try sema.isComptimeKnown(field_init))) {
-            break i;
+            break field_assign;
         }
     } else null;
 
test/cases/compile_errors/compile_time_struct_field.zig
@@ -0,0 +1,19 @@
+const S = struct {
+    comptime_field: comptime_int = 2,
+    normal_ptr: *u32,
+};
+
+export fn a() void {
+  var value: u32 = 3;
+  const comptimeStruct = S {
+    .normal_ptr = &value,
+  };
+  _ = comptimeStruct;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// 9:6: error: unable to resolve comptime value
+// 9:6: note: initializer of comptime only struct must be comptime-known