Commit 585c160c20
Changed files (2)
src
test
cases
compile_errors
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