authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-07-08 15:09:56-07:00
committergravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-07-08 19:50:28-07:00
log2fff25fd220632cc6943680d3d6bbb1f21fa141f
treec4d7be35ec022324c46761db643e2f28418cccb4
parent6f0807f50f4e946bb850e746beaa5d6556cf7750

stage2: Support initializing anonymous struct type

This commit adds support for initializing `.anon_struct` types. There is also some follow-up work to do for both tuples and structs regarding comptime fields, so this also adds some tests to keep track of that work.

3 files changed, 204 insertions(+), 129 deletions(-)

src/Sema.zig+128-129
......@@ -3326,7 +3326,7 @@ fn zirValidateStructInit(
33263326 switch (agg_ty.zigTypeTag()) {
33273327 .Struct => return sema.validateStructInit(
33283328 block,
3329 agg_ty.castTag(.@"struct").?.data,
3329 agg_ty,
33303330 init_src,
33313331 instrs,
33323332 is_comptime,
......@@ -3470,7 +3470,7 @@ fn validateUnionInit(
34703470fn validateStructInit(
34713471 sema: *Sema,
34723472 block: *Block,
3473 struct_obj: *Module.Struct,
3473 struct_ty: Type,
34743474 init_src: LazySrcLoc,
34753475 instrs: []const Zir.Inst.Index,
34763476 is_comptime: bool,
......@@ -3478,7 +3478,7 @@ fn validateStructInit(
34783478 const gpa = sema.gpa;
34793479
34803480 // Maps field index to field_ptr index of where it was already initialized.
3481 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.count());
3481 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount());
34823482 defer gpa.free(found_fields);
34833483 mem.set(Zir.Inst.Index, found_fields, 0);
34843484
......@@ -3490,8 +3490,7 @@ fn validateStructInit(
34903490 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
34913491 struct_ptr_zir_ref = field_ptr_extra.lhs;
34923492 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);
3493 const field_index = struct_obj.fields.getIndex(field_name) orelse
3494 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
3493 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
34953494 if (found_fields[field_index] != 0) {
34963495 const other_field_ptr = found_fields[field_index];
34973496 const other_field_ptr_data = sema.code.instructions.items(.data)[other_field_ptr].pl_node;
......@@ -3509,10 +3508,7 @@ fn validateStructInit(
35093508
35103509 var root_msg: ?*Module.ErrorMsg = null;
35113510
3512 const fields = struct_obj.fields.values();
35133511 const struct_ptr = try sema.resolveInst(struct_ptr_zir_ref);
3514 const struct_ty = sema.typeOf(struct_ptr).childType();
3515
35163512 if ((is_comptime or block.is_comptime) and
35173513 (try sema.resolveDefinedValue(block, init_src, struct_ptr)) != null)
35183514 {
......@@ -3522,10 +3518,9 @@ fn validateStructInit(
35223518 for (found_fields) |field_ptr, i| {
35233519 if (field_ptr != 0) continue;
35243520
3525 const field = fields[i];
3526 const field_name = struct_obj.fields.keys()[i];
3527
3528 if (field.default_val.tag() == .unreachable_value) {
3521 const default_val = struct_ty.structFieldDefaultValue(i);
3522 if (default_val.tag() == .unreachable_value) {
3523 const field_name = struct_ty.structFieldName(i);
35293524 const template = "missing struct field: {s}";
35303525 const args = .{field_name};
35313526 if (root_msg) |msg| {
......@@ -3536,22 +3531,25 @@ fn validateStructInit(
35363531 continue;
35373532 }
35383533
3539 const default_field_ptr = try sema.structFieldPtr(block, init_src, struct_ptr, field_name, init_src, struct_ty);
3540 const init = try sema.addConstant(field.ty, field.default_val);
35413534 const field_src = init_src; // TODO better source location
3535 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty);
3536 const field_ty = sema.typeOf(default_field_ptr).childType();
3537 const init = try sema.addConstant(field_ty, default_val);
35423538 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
35433539 }
35443540
35453541 if (root_msg) |msg| {
3546 const mod = sema.mod;
3547 const fqn = try struct_obj.getFullyQualifiedName(mod);
3548 defer gpa.free(fqn);
3549 try mod.errNoteNonLazy(
3550 struct_obj.srcLoc(mod),
3551 msg,
3552 "struct '{s}' declared here",
3553 .{fqn},
3554 );
3542 if (struct_ty.castTag(.@"struct")) |struct_obj| {
3543 const mod = sema.mod;
3544 const fqn = try struct_obj.data.getFullyQualifiedName(mod);
3545 defer gpa.free(fqn);
3546 try mod.errNoteNonLazy(
3547 struct_obj.data.srcLoc(mod),
3548 msg,
3549 "struct '{s}' declared here",
3550 .{fqn},
3551 );
3552 }
35553553 return sema.failWithOwnedErrorMsg(block, msg);
35563554 }
35573555
......@@ -3566,17 +3564,16 @@ fn validateStructInit(
35663564
35673565 // We collect the comptime field values in case the struct initialization
35683566 // ends up being comptime-known.
3569 const field_values = try sema.arena.alloc(Value, fields.len);
3567 const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount());
35703568
35713569 field: for (found_fields) |field_ptr, i| {
3572 const field = fields[i];
3573
35743570 if (field_ptr != 0) {
35753571 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
35763572 const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_ptr_data.src_node };
35773573
35783574 // Determine whether the value stored to this pointer is comptime-known.
3579 if (try sema.typeHasOnePossibleValue(block, field_src, field.ty)) |opv| {
3575 const field_ty = struct_ty.structFieldType(i);
3576 if (try sema.typeHasOnePossibleValue(block, field_src, field_ty)) |opv| {
35803577 field_values[i] = opv;
35813578 continue;
35823579 }
......@@ -3648,9 +3645,9 @@ fn validateStructInit(
36483645 continue :field;
36493646 }
36503647
3651 const field_name = struct_obj.fields.keys()[i];
3652
3653 if (field.default_val.tag() == .unreachable_value) {
3648 const default_val = struct_ty.structFieldDefaultValue(i);
3649 if (default_val.tag() == .unreachable_value) {
3650 const field_name = struct_ty.structFieldName(i);
36543651 const template = "missing struct field: {s}";
36553652 const args = .{field_name};
36563653 if (root_msg) |msg| {
......@@ -3660,17 +3657,20 @@ fn validateStructInit(
36603657 }
36613658 continue;
36623659 }
3660 field_values[i] = default_val;
36633661 }
36643662
36653663 if (root_msg) |msg| {
3666 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);
3667 defer gpa.free(fqn);
3668 try sema.mod.errNoteNonLazy(
3669 struct_obj.srcLoc(sema.mod),
3670 msg,
3671 "struct '{s}' declared here",
3672 .{fqn},
3673 );
3664 if (struct_ty.castTag(.@"struct")) |struct_obj| {
3665 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
3666 defer gpa.free(fqn);
3667 try sema.mod.errNoteNonLazy(
3668 struct_obj.data.srcLoc(sema.mod),
3669 msg,
3670 "struct '{s}' declared here",
3671 .{fqn},
3672 );
3673 }
36743674 return sema.failWithOwnedErrorMsg(block, msg);
36753675 }
36763676
......@@ -3679,15 +3679,6 @@ fn validateStructInit(
36793679 // instead a single `store` to the struct_ptr with a comptime struct value.
36803680
36813681 block.instructions.shrinkRetainingCapacity(first_block_index);
3682
3683 // The `field_values` array has been populated for all the non-default struct
3684 // fields. Here we fill in the default field values.
3685 for (found_fields) |field_ptr, i| {
3686 if (field_ptr != 0) continue;
3687
3688 field_values[i] = fields[i].default_val;
3689 }
3690
36913682 const struct_val = try Value.Tag.aggregate.create(sema.arena, field_values);
36923683 const struct_init = try sema.addConstant(struct_ty, struct_val);
36933684 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
......@@ -3695,16 +3686,13 @@ fn validateStructInit(
36953686 }
36963687
36973688 // Our task is to insert `store` instructions for all the default field values.
3698
36993689 for (found_fields) |field_ptr, i| {
37003690 if (field_ptr != 0) continue;
37013691
3702 const field = fields[i];
3703 const field_name = struct_obj.fields.keys()[i];
3704 const default_field_ptr = try sema.structFieldPtr(block, init_src, struct_ptr, field_name, init_src, struct_ty);
3705
3706 const init = try sema.addConstant(field.ty, field.default_val);
37073692 const field_src = init_src; // TODO better source location
3693 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty);
3694 const field_ty = sema.typeOf(default_field_ptr).childType();
3695 const init = try sema.addConstant(field_ty, field_values[i]);
37083696 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
37093697 }
37103698}
......@@ -13827,7 +13815,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1382713815 const obj_ty = try sema.resolveType(block, src, inst_data.operand);
1382813816
1382913817 switch (obj_ty.zigTypeTag()) {
13830 .Struct => return structInitEmpty(sema, block, obj_ty, src, src),
13818 .Struct => return sema.structInitEmpty(block, obj_ty, src, src),
1383113819 .Array => return arrayInitEmpty(sema, obj_ty),
1383213820 .Void => return sema.addConstant(obj_ty, Value.void),
1383313821 else => return sema.failWithArrayInitNotSupported(block, src, obj_ty),
......@@ -13844,29 +13832,13 @@ fn structInitEmpty(
1384413832 const gpa = sema.gpa;
1384513833 // This logic must be synchronized with that in `zirStructInit`.
1384613834 const struct_ty = try sema.resolveTypeFields(block, dest_src, obj_ty);
13847 const struct_obj = struct_ty.castTag(.@"struct").?.data;
1384813835
1384913836 // The init values to use for the struct instance.
13850 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_obj.fields.count());
13837 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount());
1385113838 defer gpa.free(field_inits);
13839 mem.set(Air.Inst.Ref, field_inits, .none);
1385213840
13853 var root_msg: ?*Module.ErrorMsg = null;
13854
13855 for (struct_obj.fields.values()) |field, i| {
13856 if (field.default_val.tag() == .unreachable_value) {
13857 const field_name = struct_obj.fields.keys()[i];
13858 const template = "missing struct field: {s}";
13859 const args = .{field_name};
13860 if (root_msg) |msg| {
13861 try sema.errNote(block, init_src, msg, template, args);
13862 } else {
13863 root_msg = try sema.errMsg(block, init_src, template, args);
13864 }
13865 } else {
13866 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
13867 }
13868 }
13869 return sema.finishStructInit(block, dest_src, field_inits, root_msg, struct_obj, struct_ty, false);
13841 return sema.finishStructInit(block, init_src, dest_src, field_inits, struct_ty, false);
1387013842}
1387113843
1387213844fn arrayInitEmpty(sema: *Sema, obj_ty: Type) CompileError!Air.Inst.Ref {
......@@ -13936,19 +13908,18 @@ fn zirStructInit(
1393613908 const unresolved_struct_type = try sema.resolveType(block, src, first_field_type_extra.container_type);
1393713909 const resolved_ty = try sema.resolveTypeFields(block, src, unresolved_struct_type);
1393813910
13939 if (resolved_ty.castTag(.@"struct")) |struct_payload| {
13911 if (resolved_ty.zigTypeTag() == .Struct) {
1394013912 // This logic must be synchronized with that in `zirStructInitEmpty`.
13941 const struct_obj = struct_payload.data;
1394213913
1394313914 // Maps field index to field_type index of where it was already initialized.
1394413915 // For making sure all fields are accounted for and no fields are duplicated.
13945 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.count());
13916 const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount());
1394613917 defer gpa.free(found_fields);
13947 mem.set(Zir.Inst.Index, found_fields, 0);
1394813918
1394913919 // The init values to use for the struct instance.
13950 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_obj.fields.count());
13920 const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount());
1395113921 defer gpa.free(field_inits);
13922 mem.set(Air.Inst.Ref, field_inits, .none);
1395213923
1395313924 var field_i: u32 = 0;
1395413925 var extra_index = extra.end;
......@@ -13961,9 +13932,8 @@ fn zirStructInit(
1396113932 const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_type_data.src_node };
1396213933 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
1396313934 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);
13964 const field_index = struct_obj.fields.getIndex(field_name) orelse
13965 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
13966 if (found_fields[field_index] != 0) {
13935 const field_index = try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
13936 if (field_inits[field_index] != .none) {
1396713937 const other_field_type = found_fields[field_index];
1396813938 const other_field_type_data = zir_datas[other_field_type].pl_node;
1396913939 const other_field_src: LazySrcLoc = .{ .node_offset_back2tok = other_field_type_data.src_node };
......@@ -13979,27 +13949,7 @@ fn zirStructInit(
1397913949 field_inits[field_index] = try sema.resolveInst(item.data.init);
1398013950 }
1398113951
13982 var root_msg: ?*Module.ErrorMsg = null;
13983
13984 for (found_fields) |field_type_inst, i| {
13985 if (field_type_inst != 0) continue;
13986
13987 // Check if the field has a default init.
13988 const field = struct_obj.fields.values()[i];
13989 if (field.default_val.tag() == .unreachable_value) {
13990 const field_name = struct_obj.fields.keys()[i];
13991 const template = "missing struct field: {s}";
13992 const args = .{field_name};
13993 if (root_msg) |msg| {
13994 try sema.errNote(block, src, msg, template, args);
13995 } else {
13996 root_msg = try sema.errMsg(block, src, template, args);
13997 }
13998 } else {
13999 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
14000 }
14001 }
14002 return sema.finishStructInit(block, src, field_inits, root_msg, struct_obj, resolved_ty, is_ref);
13952 return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref);
1400313953 } else if (resolved_ty.zigTypeTag() == .Union) {
1400413954 if (extra.data.fields_len != 1) {
1400513955 return sema.fail(block, src, "union initialization expects exactly one field", .{});
......@@ -14051,29 +14001,69 @@ fn zirStructInit(
1405114001fn finishStructInit(
1405214002 sema: *Sema,
1405314003 block: *Block,
14054 src: LazySrcLoc,
14055 field_inits: []const Air.Inst.Ref,
14056 root_msg: ?*Module.ErrorMsg,
14057 struct_obj: *Module.Struct,
14004 init_src: LazySrcLoc,
14005 dest_src: LazySrcLoc,
14006 field_inits: []Air.Inst.Ref,
1405814007 struct_ty: Type,
1405914008 is_ref: bool,
14060) !Air.Inst.Ref {
14009) CompileError!Air.Inst.Ref {
1406114010 const gpa = sema.gpa;
1406214011
14012 var root_msg: ?*Module.ErrorMsg = null;
14013 if (struct_ty.isAnonStruct()) {
14014 const struct_obj = struct_ty.castTag(.anon_struct).?.data;
14015 for (struct_obj.values) |default_val, i| {
14016 if (field_inits[i] != .none) continue;
14017
14018 if (default_val.tag() == .unreachable_value) {
14019 const field_name = struct_obj.names[i];
14020 const template = "missing struct field: {s}";
14021 const args = .{field_name};
14022 if (root_msg) |msg| {
14023 try sema.errNote(block, init_src, msg, template, args);
14024 } else {
14025 root_msg = try sema.errMsg(block, init_src, template, args);
14026 }
14027 } else {
14028 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
14029 }
14030 }
14031 } else {
14032 const struct_obj = struct_ty.castTag(.@"struct").?.data;
14033 for (struct_obj.fields.values()) |field, i| {
14034 if (field_inits[i] != .none) continue;
14035
14036 if (field.default_val.tag() == .unreachable_value) {
14037 const field_name = struct_obj.fields.keys()[i];
14038 const template = "missing struct field: {s}";
14039 const args = .{field_name};
14040 if (root_msg) |msg| {
14041 try sema.errNote(block, init_src, msg, template, args);
14042 } else {
14043 root_msg = try sema.errMsg(block, init_src, template, args);
14044 }
14045 } else {
14046 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
14047 }
14048 }
14049 }
14050
1406314051 if (root_msg) |msg| {
14064 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);
14065 defer gpa.free(fqn);
14066 try sema.mod.errNoteNonLazy(
14067 struct_obj.srcLoc(sema.mod),
14068 msg,
14069 "struct '{s}' declared here",
14070 .{fqn},
14071 );
14052 if (struct_ty.castTag(.@"struct")) |struct_obj| {
14053 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
14054 defer gpa.free(fqn);
14055 try sema.mod.errNoteNonLazy(
14056 struct_obj.data.srcLoc(sema.mod),
14057 msg,
14058 "struct '{s}' declared here",
14059 .{fqn},
14060 );
14061 }
1407214062 return sema.failWithOwnedErrorMsg(block, msg);
1407314063 }
1407414064
1407514065 const is_comptime = for (field_inits) |field_init| {
14076 if (!(try sema.isComptimeKnown(block, src, field_init))) {
14066 if (!(try sema.isComptimeKnown(block, dest_src, field_init))) {
1407714067 break false;
1407814068 }
1407914069 } else true;
......@@ -14081,10 +14071,10 @@ fn finishStructInit(
1408114071 if (is_comptime) {
1408214072 const values = try sema.arena.alloc(Value, field_inits.len);
1408314073 for (field_inits) |field_init, i| {
14084 values[i] = (sema.resolveMaybeUndefVal(block, src, field_init) catch unreachable).?;
14074 values[i] = (sema.resolveMaybeUndefVal(block, dest_src, field_init) catch unreachable).?;
1408514075 }
1408614076 const struct_val = try Value.Tag.aggregate.create(sema.arena, values);
14087 return sema.addConstantMaybeRef(block, src, struct_ty, struct_val, is_ref);
14077 return sema.addConstantMaybeRef(block, dest_src, struct_ty, struct_val, is_ref);
1408814078 }
1408914079
1409014080 if (is_ref) {
......@@ -14096,15 +14086,15 @@ fn finishStructInit(
1409614086 const alloc = try block.addTy(.alloc, alloc_ty);
1409714087 for (field_inits) |field_init, i_usize| {
1409814088 const i = @intCast(u32, i_usize);
14099 const field_src = src;
14100 const field_ptr = try sema.structFieldPtrByIndex(block, src, alloc, i, struct_obj, field_src);
14101 try sema.storePtr(block, src, field_ptr, field_init);
14089 const field_src = dest_src;
14090 const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, alloc, i, field_src, struct_ty);
14091 try sema.storePtr(block, dest_src, field_ptr, field_init);
1410214092 }
1410314093
1410414094 return alloc;
1410514095 }
1410614096
14107 try sema.requireRuntimeBlock(block, src);
14097 try sema.requireRuntimeBlock(block, dest_src);
1410814098 try sema.queueFullTypeResolution(struct_ty);
1410914099 return block.addAggregateInit(struct_ty, field_inits);
1411014100}
......@@ -19059,7 +19049,7 @@ fn structFieldPtr(
1905919049 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
1906019050 const field_index = @intCast(u32, field_index_big);
1906119051
19062 return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, struct_obj, field_name_src);
19052 return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, field_name_src, struct_ty);
1906319053}
1906419054
1906519055fn structFieldPtrByIndex(
......@@ -19068,9 +19058,14 @@ fn structFieldPtrByIndex(
1906819058 src: LazySrcLoc,
1906919059 struct_ptr: Air.Inst.Ref,
1907019060 field_index: u32,
19071 struct_obj: *Module.Struct,
1907219061 field_src: LazySrcLoc,
19062 struct_ty: Type,
1907319063) CompileError!Air.Inst.Ref {
19064 if (struct_ty.isAnonStruct()) {
19065 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index);
19066 }
19067
19068 const struct_obj = struct_ty.castTag(.@"struct").?.data;
1907419069 const field = struct_obj.fields.values()[field_index];
1907519070 const struct_ptr_ty = sema.typeOf(struct_ptr);
1907619071 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo().data;
......@@ -20356,7 +20351,7 @@ fn coerce(
2035620351 },
2035720352 .Struct => {
2035820353 if (inst == .empty_struct) {
20359 return structInitEmpty(sema, block, dest_ty, dest_ty_src, inst_src);
20354 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);
2036020355 }
2036120356 if (inst_ty.isTupleOrAnonStruct()) {
2036220357 return sema.coerceTupleToStruct(block, dest_ty, dest_ty_src, inst, inst_src);
......@@ -25754,10 +25749,14 @@ fn structFieldIndex(
2575425749 field_src: LazySrcLoc,
2575525750) !u32 {
2575625751 const struct_ty = try sema.resolveTypeFields(block, field_src, unresolved_struct_ty);
25757 const struct_obj = struct_ty.castTag(.@"struct").?.data;
25758 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
25759 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
25760 return @intCast(u32, field_index_usize);
25752 if (struct_ty.isAnonStruct()) {
25753 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
25754 } else {
25755 const struct_obj = struct_ty.castTag(.@"struct").?.data;
25756 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
25757 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
25758 return @intCast(u32, field_index_usize);
25759 }
2576125760}
2576225761
2576325762fn anonStructFieldIndex(
src/type.zig+18
......@@ -5432,6 +5432,24 @@ pub const Type = extern union {
54325432 }
54335433 }
54345434
5435 pub fn structFieldDefaultValue(ty: Type, index: usize) Value {
5436 switch (ty.tag()) {
5437 .@"struct" => {
5438 const struct_obj = ty.castTag(.@"struct").?.data;
5439 return struct_obj.fields.values()[index].default_val;
5440 },
5441 .tuple => {
5442 const tuple = ty.castTag(.tuple).?.data;
5443 return tuple.values[index];
5444 },
5445 .anon_struct => {
5446 const struct_obj = ty.castTag(.anon_struct).?.data;
5447 return struct_obj.values[index];
5448 },
5449 else => unreachable,
5450 }
5451 }
5452
54355453 pub fn structFieldValueComptime(ty: Type, index: usize) ?Value {
54365454 switch (ty.tag()) {
54375455 .@"struct" => {
test/behavior/tuple.zig+58
......@@ -197,3 +197,61 @@ test "initializing tuple with explicit type" {
197197 var a = T{ 0, 0 };
198198 _ = a;
199199}
200
201test "initializing anon struct with explicit type" {
202 const T = @TypeOf(.{ .foo = @as(i32, 1), .bar = @as(i32, 2) });
203 var a = T{ .foo = 1, .bar = 2 };
204 _ = a;
205}
206
207test "fieldParentPtr of tuple" {
208 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
209
210 var x: u32 = 0;
211 const tuple = .{ x, x };
212 try testing.expect(&tuple == @fieldParentPtr(@TypeOf(tuple), "1", &tuple[1]));
213}
214
215test "fieldParentPtr of anon struct" {
216 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
217
218 var x: u32 = 0;
219 const anon_st = .{ .foo = x, .bar = x };
220 try testing.expect(&anon_st == @fieldParentPtr(@TypeOf(anon_st), "bar", &anon_st.bar));
221}
222
223test "offsetOf tuple" {
224 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
225
226 var x: u32 = 0;
227 const T = @TypeOf(.{ x, x });
228
229 _ = @offsetOf(T, "1");
230}
231
232test "offsetOf anon struct" {
233 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
234
235 var x: u32 = 0;
236 const T = @TypeOf(.{ .foo = x, .bar = x });
237
238 _ = @offsetOf(T, "bar");
239}
240
241test "initializing tuple with mixed comptime-runtime fields" {
242 if (true) return error.SkipZigTest; // TODO
243
244 var x: u32 = 15;
245 const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
246 var a: T = .{ -1234, 5678, x + 1 };
247 _ = a;
248}
249
250test "initializing anon struct with mixed comptime-runtime fields" {
251 if (true) return error.SkipZigTest; // TODO
252
253 var x: u32 = 15;
254 const T = @TypeOf(.{ .foo = @as(i32, -1234), .bar = x });
255 var a: T = .{ .foo = -1234, .bar = x + 1 };
256 _ = a;
257}