Commit 585c160c20

Veikka Tuominen <git@vexu.eu>
2022-07-20 18:47:54
Sema: handle store to comptime field when `ResultLoc == .none`
1 parent 9465906
Changed files (2)
src
test
src/Sema.zig
@@ -14515,6 +14515,16 @@ fn zirStructInit(
             }
             found_fields[field_index] = item.data.field_type;
             field_inits[field_index] = try sema.resolveInst(item.data.init);
+            if (resolved_ty.structFieldValueComptime(field_index)) |default_value| {
+                const init_val = (try sema.resolveMaybeUndefVal(block, field_src, field_inits[field_index])) orelse {
+                    return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime known");
+                };
+
+                if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index), sema.mod)) {
+                    // TODO add note showing where default value is provided
+                    return sema.fail(block, field_src, "value stored in comptime field does not match the default value of the field", .{});
+                }
+            }
         }
 
         return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref);
@@ -23688,6 +23698,7 @@ fn coerceTupleToStruct(
     const struct_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty);
 
     if (struct_ty.isTupleOrAnonStruct()) {
+        // NOTE remember to handle comptime fields
         return sema.fail(block, dest_ty_src, "TODO: implement coercion from tuples to tuples", .{});
     }
 
@@ -23708,12 +23719,19 @@ fn coerceTupleToStruct(
             try std.fmt.allocPrint(sema.arena, "{d}", .{i});
         const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
         const field = fields.values()[field_index];
-        if (field.is_comptime) {
-            return sema.fail(block, dest_ty_src, "TODO: implement coercion from tuples to structs when one of the destination struct fields is comptime", .{});
-        }
         const elem_ref = try tupleField(sema, block, inst_src, inst, field_src, i);
         const coerced = try sema.coerce(block, field.ty, elem_ref, field_src);
         field_refs[field_index] = coerced;
+        if (field.is_comptime) {
+            const init_val = (try sema.resolveMaybeUndefVal(block, field_src, coerced)) orelse {
+                return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime known");
+            };
+
+            if (!init_val.eql(field.default_val, field.ty, sema.mod)) {
+                // TODO add note showing where default value is provided
+                return sema.fail(block, field_src, "value stored in comptime field does not match the default value of the field", .{});
+            }
+        }
         if (runtime_src == null) {
             if (try sema.resolveMaybeUndefVal(block, field_src, coerced)) |field_val| {
                 field_vals[field_index] = field_val;
test/cases/compile_errors/invalid_store_to_comptime_field.zig
@@ -20,6 +20,35 @@ pub export fn entry2() void {
     _ = list2;
     _ = list3;
 }
+pub export fn entry3() void {
+    const U = struct {
+        comptime foo: u32 = 1,
+        bar: u32,
+        fn foo(x: @This()) void {
+            _ = x;
+        }
+    };
+    _ = U.foo(U{ .foo = 2, .bar = 2 });
+}
+pub export fn entry4() void {
+    const U = struct {
+        comptime foo: u32 = 1,
+        bar: u32,
+        fn foo(x: @This()) void {
+            _ = x;
+        }
+    };
+    _ = U.foo(.{ .foo = 2, .bar = 2 });
+}
+// pub export fn entry5() void {
+//     var x: u32 = 15;
+//     const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
+//     const S = struct {
+//         fn foo(_: T) void {}
+//     };
+//     _ = S.foo(.{ -1234, 5679, x });
+// }
+
 
 // error
 // target=native
@@ -28,3 +57,5 @@ pub export fn entry2() void {
 // :6:19: error: value stored in comptime field does not match the default value of the field
 // :14:19: error: value stored in comptime field does not match the default value of the field
 // :19:38: error: value stored in comptime field does not match the default value of the field
+// :31:19: error: value stored in comptime field does not match the default value of the field
+// :41:14: error: value stored in comptime field does not match the default value of the field