authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-19 14:36:31+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-23 15:40:12+03:00
log9465906775620a0832b19370b42ef2b193b96356
treee11f3469b911a10799a63cc418c4b30db5680f02
parentcf87026e52f7faa090c5fa922d5649f5ec2f1831

Sema: return `.comptime_field_ptr`s for tuples


2 files changed, 45 insertions(+), 13 deletions(-)

src/Sema.zig+36-13
...@@ -3659,7 +3659,10 @@ fn validateStructInit(...@@ -3659,7 +3659,10 @@ fn validateStructInit(
3659 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;3659 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
3660 struct_ptr_zir_ref = field_ptr_extra.lhs;3660 struct_ptr_zir_ref = field_ptr_extra.lhs;
3661 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);3661 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);
3662 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);3662 const field_index = if (struct_ty.isTuple())
3663 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src)
3664 else
3665 try sema.structFieldIndex(block, struct_ty, field_name, field_src);
3663 if (found_fields[field_index] != 0) {3666 if (found_fields[field_index] != 0) {
3664 const other_field_ptr = found_fields[field_index];3667 const other_field_ptr = found_fields[field_index];
3665 const other_field_ptr_data = sema.code.instructions.items(.data)[other_field_ptr].pl_node;3668 const other_field_ptr_data = sema.code.instructions.items(.data)[other_field_ptr].pl_node;
...@@ -3701,7 +3704,7 @@ fn validateStructInit(...@@ -3701,7 +3704,7 @@ fn validateStructInit(
3701 }3704 }
37023705
3703 const field_src = init_src; // TODO better source location3706 const field_src = init_src; // TODO better source location
3704 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty);3707 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
3705 const field_ty = sema.typeOf(default_field_ptr).childType();3708 const field_ty = sema.typeOf(default_field_ptr).childType();
3706 const init = try sema.addConstant(field_ty, default_val);3709 const init = try sema.addConstant(field_ty, default_val);
3707 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);3710 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
...@@ -3859,7 +3862,7 @@ fn validateStructInit(...@@ -3859,7 +3862,7 @@ fn validateStructInit(
3859 if (field_ptr != 0) continue;3862 if (field_ptr != 0) continue;
38603863
3861 const field_src = init_src; // TODO better source location3864 const field_src = init_src; // TODO better source location
3862 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty);3865 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
3863 const field_ty = sema.typeOf(default_field_ptr).childType();3866 const field_ty = sema.typeOf(default_field_ptr).childType();
3864 const init = try sema.addConstant(field_ty, field_values[i]);3867 const init = try sema.addConstant(field_ty, field_values[i]);
3865 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);3868 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
...@@ -14494,7 +14497,10 @@ fn zirStructInit(...@@ -14494,7 +14497,10 @@ fn zirStructInit(
14494 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };14497 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };
14495 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;14498 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
14496 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);14499 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);
14497 const field_index = try sema.structFieldIndex(block, resolved_ty, field_name, field_src);14500 const field_index = if (resolved_ty.isTuple())
14501 try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src)
14502 else
14503 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
14498 if (field_inits[field_index] != .none) {14504 if (field_inits[field_index] != .none) {
14499 const other_field_type = found_fields[field_index];14505 const other_field_type = found_fields[field_index];
14500 const other_field_type_data = zir_datas[other_field_type].pl_node;14506 const other_field_type_data = zir_datas[other_field_type].pl_node;
...@@ -14649,7 +14655,7 @@ fn finishStructInit(...@@ -14649,7 +14655,7 @@ fn finishStructInit(
14649 for (field_inits) |field_init, i_usize| {14655 for (field_inits) |field_init, i_usize| {
14650 const i = @intCast(u32, i_usize);14656 const i = @intCast(u32, i_usize);
14651 const field_src = dest_src;14657 const field_src = dest_src;
14652 const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, alloc, i, field_src, struct_ty);14658 const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, alloc, i, field_src, struct_ty, true);
14653 try sema.storePtr(block, dest_src, field_ptr, field_init);14659 try sema.storePtr(block, dest_src, field_ptr, field_init);
14654 }14660 }
1465514661
...@@ -19398,7 +19404,7 @@ fn fieldVal(...@@ -19398,7 +19404,7 @@ fn fieldVal(
19398 },19404 },
19399 .Struct => if (is_pointer_to) {19405 .Struct => if (is_pointer_to) {
19400 // Avoid loading the entire struct by fetching a pointer and loading that19406 // Avoid loading the entire struct by fetching a pointer and loading that
19401 const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty);19407 const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false);
19402 return sema.analyzeLoad(block, src, field_ptr, object_src);19408 return sema.analyzeLoad(block, src, field_ptr, object_src);
19403 } else {19409 } else {
19404 return sema.structFieldVal(block, src, object, field_name, field_name_src, inner_ty);19410 return sema.structFieldVal(block, src, object, field_name, field_name_src, inner_ty);
...@@ -19607,7 +19613,7 @@ fn fieldPtr(...@@ -19607,7 +19613,7 @@ fn fieldPtr(
19607 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)19613 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)
19608 else19614 else
19609 object_ptr;19615 object_ptr;
19610 return sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty);19616 return sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing);
19611 },19617 },
19612 .Union => {19618 .Union => {
19613 const inner_ptr = if (is_pointer_to)19619 const inner_ptr = if (is_pointer_to)
...@@ -19816,6 +19822,7 @@ fn structFieldPtr(...@@ -19816,6 +19822,7 @@ fn structFieldPtr(
19816 field_name: []const u8,19822 field_name: []const u8,
19817 field_name_src: LazySrcLoc,19823 field_name_src: LazySrcLoc,
19818 unresolved_struct_ty: Type,19824 unresolved_struct_ty: Type,
19825 initializing: bool,
19819) CompileError!Air.Inst.Ref {19826) CompileError!Air.Inst.Ref {
19820 assert(unresolved_struct_ty.zigTypeTag() == .Struct);19827 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
1982119828
...@@ -19828,10 +19835,10 @@ fn structFieldPtr(...@@ -19828,10 +19835,10 @@ fn structFieldPtr(
19828 return sema.analyzeRef(block, src, len_inst);19835 return sema.analyzeRef(block, src, len_inst);
19829 }19836 }
19830 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);19837 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
19831 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index);19838 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
19832 } else if (struct_ty.isAnonStruct()) {19839 } else if (struct_ty.isAnonStruct()) {
19833 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);19840 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
19834 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index);19841 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
19835 }19842 }
1983619843
19837 const struct_obj = struct_ty.castTag(.@"struct").?.data;19844 const struct_obj = struct_ty.castTag(.@"struct").?.data;
...@@ -19840,7 +19847,7 @@ fn structFieldPtr(...@@ -19840,7 +19847,7 @@ fn structFieldPtr(
19840 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);19847 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
19841 const field_index = @intCast(u32, field_index_big);19848 const field_index = @intCast(u32, field_index_big);
1984219849
19843 return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, field_name_src, struct_ty);19850 return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, field_name_src, struct_ty, initializing);
19844}19851}
1984519852
19846fn structFieldPtrByIndex(19853fn structFieldPtrByIndex(
...@@ -19851,9 +19858,10 @@ fn structFieldPtrByIndex(...@@ -19851,9 +19858,10 @@ fn structFieldPtrByIndex(
19851 field_index: u32,19858 field_index: u32,
19852 field_src: LazySrcLoc,19859 field_src: LazySrcLoc,
19853 struct_ty: Type,19860 struct_ty: Type,
19861 initializing: bool,
19854) CompileError!Air.Inst.Ref {19862) CompileError!Air.Inst.Ref {
19855 if (struct_ty.isAnonStruct()) {19863 if (struct_ty.isAnonStruct()) {
19856 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index);19864 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);
19857 }19865 }
1985819866
19859 const struct_obj = struct_ty.castTag(.@"struct").?.data;19867 const struct_obj = struct_ty.castTag(.@"struct").?.data;
...@@ -20050,6 +20058,10 @@ fn tupleFieldValByIndex(...@@ -20050,6 +20058,10 @@ fn tupleFieldValByIndex(
20050 return sema.addConstant(field_ty, field_values[field_index]);20058 return sema.addConstant(field_ty, field_values[field_index]);
20051 }20059 }
2005220060
20061 if (tuple_ty.structFieldValueComptime(field_index)) |default_val| {
20062 return sema.addConstant(field_ty, default_val);
20063 }
20064
20053 try sema.requireRuntimeBlock(block, src, null);20065 try sema.requireRuntimeBlock(block, src, null);
20054 return block.addStructFieldVal(tuple_byval, field_index, field_ty);20066 return block.addStructFieldVal(tuple_byval, field_index, field_ty);
20055}20067}
...@@ -20250,7 +20262,7 @@ fn elemPtr(...@@ -20250,7 +20262,7 @@ fn elemPtr(
20250 // Tuple field access.20262 // Tuple field access.
20251 const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime known");20263 const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime known");
20252 const index = @intCast(u32, index_val.toUnsignedInt(target));20264 const index = @intCast(u32, index_val.toUnsignedInt(target));
20253 return sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index);20265 return sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init);
20254 },20266 },
20255 else => unreachable,20267 else => unreachable,
20256 }20268 }
...@@ -20353,6 +20365,7 @@ fn tupleFieldPtr(...@@ -20353,6 +20365,7 @@ fn tupleFieldPtr(
20353 tuple_ptr: Air.Inst.Ref,20365 tuple_ptr: Air.Inst.Ref,
20354 field_index_src: LazySrcLoc,20366 field_index_src: LazySrcLoc,
20355 field_index: u32,20367 field_index: u32,
20368 init: bool,
20356) CompileError!Air.Inst.Ref {20369) CompileError!Air.Inst.Ref {
20357 const tuple_ptr_ty = sema.typeOf(tuple_ptr);20370 const tuple_ptr_ty = sema.typeOf(tuple_ptr);
20358 const tuple_ty = tuple_ptr_ty.childType();20371 const tuple_ty = tuple_ptr_ty.childType();
...@@ -20386,7 +20399,17 @@ fn tupleFieldPtr(...@@ -20386,7 +20399,17 @@ fn tupleFieldPtr(
20386 );20399 );
20387 }20400 }
2038820401
20389 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_ptr_src);20402 if (tuple_ty.structFieldValueComptime(field_index)) |default_val| {
20403 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
20404 .field_ty = field_ty,
20405 .field_val = default_val,
20406 });
20407 return sema.addConstant(ptr_field_ty, val);
20408 }
20409
20410 if (!init) {
20411 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_ptr_src);
20412 }
2039020413
20391 try sema.requireRuntimeBlock(block, tuple_ptr_src, null);20414 try sema.requireRuntimeBlock(block, tuple_ptr_src, null);
20392 return block.addStructFieldPtr(tuple_ptr, field_index, ptr_field_ty);20415 return block.addStructFieldPtr(tuple_ptr, field_index, ptr_field_ty);
test/cases/compile_errors/invalid_store_to_comptime_field.zig+9
...@@ -13,9 +13,18 @@ pub export fn entry1() void {...@@ -13,9 +13,18 @@ pub export fn entry1() void {
13 var s: S = .{};13 var s: S = .{};
14 s.a = T{ .a = 2, .b = 2 };14 s.a = T{ .a = 2, .b = 2 };
15}15}
16pub export fn entry2() void {
17 var list = .{ 1, 2, 3 };
18 var list2 = @TypeOf(list){ .@"0" = 1, .@"1" = 2, .@"2" = 3 };
19 var list3 = @TypeOf(list){ 1, 2, 4 };
20 _ = list2;
21 _ = list3;
22}
23
16// error24// error
17// target=native25// target=native
18// backend=stage226// backend=stage2
19//27//
20// :6:19: error: value stored in comptime field does not match the default value of the field28// :6:19: error: value stored in comptime field does not match the default value of the field
21// :14:19: error: value stored in comptime field does not match the default value of the field29// :14:19: error: value stored in comptime field does not match the default value of the field
30// :19:38: error: value stored in comptime field does not match the default value of the field