| ... | ... | @@ -2733,7 +2733,7 @@ fn zirValidateStructInit( |
| 2733 | 2733 | ), |
| 2734 | 2734 | .Union => return sema.validateUnionInit( |
| 2735 | 2735 | block, |
| 2736 | | agg_ty.cast(Type.Payload.Union).?.data, |
| 2736 | agg_ty, |
| 2737 | 2737 | init_src, |
| 2738 | 2738 | instrs, |
| 2739 | 2739 | object_ptr, |
| ... | ... | @@ -2746,12 +2746,14 @@ fn zirValidateStructInit( |
| 2746 | 2746 | fn validateUnionInit( |
| 2747 | 2747 | sema: *Sema, |
| 2748 | 2748 | block: *Block, |
| 2749 | | union_obj: *Module.Union, |
| 2749 | union_ty: Type, |
| 2750 | 2750 | init_src: LazySrcLoc, |
| 2751 | 2751 | instrs: []const Zir.Inst.Index, |
| 2752 | 2752 | union_ptr: Air.Inst.Ref, |
| 2753 | 2753 | is_comptime: bool, |
| 2754 | 2754 | ) CompileError!void { |
| 2755 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 2756 | |
| 2755 | 2757 | if (instrs.len != 1) { |
| 2756 | 2758 | const msg = msg: { |
| 2757 | 2759 | const msg = try sema.errMsg( |
| ... | ... | @@ -2767,7 +2769,7 @@ fn validateUnionInit( |
| 2767 | 2769 | const inst_src: LazySrcLoc = .{ .node_offset_back2tok = inst_data.src_node }; |
| 2768 | 2770 | try sema.errNote(block, inst_src, msg, "additional initializer here", .{}); |
| 2769 | 2771 | } |
| 2770 | | try sema.mod.errNoteNonLazy(union_obj.srcLoc(), msg, "union declared here", .{}); |
| 2772 | try sema.addDeclaredHereNote(msg, union_ty); |
| 2771 | 2773 | break :msg msg; |
| 2772 | 2774 | }; |
| 2773 | 2775 | return sema.failWithOwnedErrorMsg(msg); |
| ... | ... | @@ -2783,9 +2785,7 @@ fn validateUnionInit( |
| 2783 | 2785 | const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_ptr_data.src_node }; |
| 2784 | 2786 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| 2785 | 2787 | const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start); |
| 2786 | | const field_index_big = union_obj.fields.getIndex(field_name) orelse |
| 2787 | | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 2788 | | const field_index = @intCast(u32, field_index_big); |
| 2788 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); |
| 2789 | 2789 | const air_tags = sema.air_instructions.items(.tag); |
| 2790 | 2790 | const air_datas = sema.air_instructions.items(.data); |
| 2791 | 2791 | const field_ptr_air_ref = sema.inst_map.get(field_ptr).?; |
| ... | ... | @@ -2844,7 +2844,6 @@ fn validateUnionInit( |
| 2844 | 2844 | .tag = tag_val, |
| 2845 | 2845 | .val = val, |
| 2846 | 2846 | }); |
| 2847 | | const union_ty = sema.typeOf(union_ptr).childType(); |
| 2848 | 2847 | const union_init = try sema.addConstant(union_ty, union_val); |
| 2849 | 2848 | try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store); |
| 2850 | 2849 | return; |
| ... | ... | @@ -11494,10 +11493,7 @@ fn unionInit( |
| 11494 | 11493 | field_name: []const u8, |
| 11495 | 11494 | field_src: LazySrcLoc, |
| 11496 | 11495 | ) CompileError!Air.Inst.Ref { |
| 11497 | | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 11498 | | const field_index_usize = union_obj.fields.getIndex(field_name) orelse |
| 11499 | | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 11500 | | const field_index = @intCast(u32, field_index_usize); |
| 11496 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); |
| 11501 | 11497 | |
| 11502 | 11498 | if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| { |
| 11503 | 11499 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); |
| ... | ... | @@ -11594,9 +11590,7 @@ fn zirStructInit( |
| 11594 | 11590 | } |
| 11595 | 11591 | } |
| 11596 | 11592 | return sema.finishStructInit(block, src, field_inits, root_msg, struct_obj, resolved_ty, is_ref); |
| 11597 | | } else if (resolved_ty.cast(Type.Payload.Union)) |union_payload| { |
| 11598 | | const union_obj = union_payload.data; |
| 11599 | | |
| 11593 | } else if (resolved_ty.zigTypeTag() == .Union) { |
| 11600 | 11594 | if (extra.data.fields_len != 1) { |
| 11601 | 11595 | return sema.fail(block, src, "union initialization expects exactly one field", .{}); |
| 11602 | 11596 | } |
| ... | ... | @@ -11607,9 +11601,7 @@ fn zirStructInit( |
| 11607 | 11601 | const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_type_data.src_node }; |
| 11608 | 11602 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 11609 | 11603 | const field_name = sema.code.nullTerminatedString(field_type_extra.name_start); |
| 11610 | | const field_index_usize = union_obj.fields.getIndex(field_name) orelse |
| 11611 | | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 11612 | | const field_index = @intCast(u32, field_index_usize); |
| 11604 | const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src); |
| 11613 | 11605 | |
| 11614 | 11606 | if (is_ref) { |
| 11615 | 11607 | return sema.fail(block, src, "TODO: Sema.zirStructInit is_ref=true union", .{}); |
| ... | ... | @@ -11732,7 +11724,11 @@ fn zirStructInitAnon( |
| 11732 | 11724 | |
| 11733 | 11725 | if (is_ref) { |
| 11734 | 11726 | const target = sema.mod.getTarget(); |
| 11735 | | const alloc = try block.addTy(.alloc, tuple_ty); |
| 11727 | const alloc_ty = try Type.ptr(sema.arena, target, .{ |
| 11728 | .pointee_type = tuple_ty, |
| 11729 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 11730 | }); |
| 11731 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 11736 | 11732 | var extra_index = extra.end; |
| 11737 | 11733 | for (types) |field_ty, i_usize| { |
| 11738 | 11734 | const i = @intCast(u32, i_usize); |
| ... | ... | @@ -11882,7 +11878,11 @@ fn zirArrayInitAnon( |
| 11882 | 11878 | |
| 11883 | 11879 | if (is_ref) { |
| 11884 | 11880 | const target = sema.mod.getTarget(); |
| 11885 | | const alloc = try block.addTy(.alloc, tuple_ty); |
| 11881 | const alloc_ty = try Type.ptr(sema.arena, target, .{ |
| 11882 | .pointee_type = tuple_ty, |
| 11883 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 11884 | }); |
| 11885 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 11886 | 11886 | for (operands) |operand, i_usize| { |
| 11887 | 11887 | const i = @intCast(u32, i_usize); |
| 11888 | 11888 | const field_ptr_ty = try Type.ptr(sema.arena, target, .{ |
| ... | ... | @@ -15220,11 +15220,7 @@ fn unionFieldPtr( |
| 15220 | 15220 | const union_ptr_ty = sema.typeOf(union_ptr); |
| 15221 | 15221 | const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty); |
| 15222 | 15222 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 15223 | | |
| 15224 | | const field_index_big = union_obj.fields.getIndex(field_name) orelse |
| 15225 | | return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name); |
| 15226 | | const field_index = @intCast(u32, field_index_big); |
| 15227 | | |
| 15223 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 15228 | 15224 | const field = union_obj.fields.values()[field_index]; |
| 15229 | 15225 | const target = sema.mod.getTarget(); |
| 15230 | 15226 | const ptr_field_ty = try Type.ptr(arena, target, .{ |
| ... | ... | @@ -15286,10 +15282,7 @@ fn unionFieldVal( |
| 15286 | 15282 | |
| 15287 | 15283 | const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty); |
| 15288 | 15284 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 15289 | | |
| 15290 | | const field_index_usize = union_obj.fields.getIndex(field_name) orelse |
| 15291 | | return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name); |
| 15292 | | const field_index = @intCast(u32, field_index_usize); |
| 15285 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 15293 | 15286 | const field = union_obj.fields.values()[field_index]; |
| 15294 | 15287 | |
| 15295 | 15288 | if (try sema.resolveMaybeUndefVal(block, src, union_byval)) |union_val| { |
| ... | ... | @@ -15799,6 +15792,15 @@ fn coerce( |
| 15799 | 15792 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 15800 | 15793 | } |
| 15801 | 15794 | |
| 15795 | // cast from pointer to anonymous struct to pointer to union |
| 15796 | if (dest_info.pointee_type.zigTypeTag() == .Union and |
| 15797 | inst_ty.zigTypeTag() == .Pointer and |
| 15798 | inst_ty.childType().tag() == .anon_struct and |
| 15799 | !dest_info.mutable) |
| 15800 | { |
| 15801 | return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src); |
| 15802 | } |
| 15803 | |
| 15802 | 15804 | // This will give an extra hint on top of what the bottom of this func would provide. |
| 15803 | 15805 | try sema.checkPtrOperand(block, dest_ty_src, inst_ty); |
| 15804 | 15806 | }, |
| ... | ... | @@ -15956,8 +15958,8 @@ fn coerce( |
| 15956 | 15958 | .Union => switch (inst_ty.zigTypeTag()) { |
| 15957 | 15959 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), |
| 15958 | 15960 | .Struct => { |
| 15959 | | if (inst_ty.castTag(.anon_struct)) |anon_struct| { |
| 15960 | | return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src, anon_struct.data); |
| 15961 | if (inst_ty.isAnonStruct()) { |
| 15962 | return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src); |
| 15961 | 15963 | } |
| 15962 | 15964 | }, |
| 15963 | 15965 | else => {}, |
| ... | ... | @@ -17047,8 +17049,9 @@ fn coerceAnonStructToUnion( |
| 17047 | 17049 | union_ty_src: LazySrcLoc, |
| 17048 | 17050 | inst: Air.Inst.Ref, |
| 17049 | 17051 | inst_src: LazySrcLoc, |
| 17050 | | anon_struct: Type.Payload.AnonStruct.Data, |
| 17051 | 17052 | ) !Air.Inst.Ref { |
| 17053 | const inst_ty = sema.typeOf(inst); |
| 17054 | const anon_struct = inst_ty.castTag(.anon_struct).?.data; |
| 17052 | 17055 | if (anon_struct.types.len != 1) { |
| 17053 | 17056 | const msg = msg: { |
| 17054 | 17057 | const msg = try sema.errMsg( |
| ... | ... | @@ -17069,11 +17072,24 @@ fn coerceAnonStructToUnion( |
| 17069 | 17072 | } |
| 17070 | 17073 | |
| 17071 | 17074 | const field_name = anon_struct.names[0]; |
| 17072 | | const inst_ty = sema.typeOf(inst); |
| 17073 | 17075 | const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty); |
| 17074 | 17076 | return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src); |
| 17075 | 17077 | } |
| 17076 | 17078 | |
| 17079 | fn coerceAnonStructToUnionPtrs( |
| 17080 | sema: *Sema, |
| 17081 | block: *Block, |
| 17082 | ptr_union_ty: Type, |
| 17083 | union_ty_src: LazySrcLoc, |
| 17084 | ptr_anon_struct: Air.Inst.Ref, |
| 17085 | anon_struct_src: LazySrcLoc, |
| 17086 | ) !Air.Inst.Ref { |
| 17087 | const union_ty = ptr_union_ty.childType(); |
| 17088 | const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src); |
| 17089 | const union_inst = try sema.coerceAnonStructToUnion(block, union_ty, union_ty_src, anon_struct, anon_struct_src); |
| 17090 | return sema.analyzeRef(block, union_ty_src, union_inst); |
| 17091 | } |
| 17092 | |
| 17077 | 17093 | /// If the lengths match, coerces element-wise. |
| 17078 | 17094 | fn coerceArrayLike( |
| 17079 | 17095 | sema: *Sema, |
| ... | ... | @@ -20080,3 +20096,17 @@ pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C |
| 20080 | 20096 | } |
| 20081 | 20097 | return true; |
| 20082 | 20098 | } |
| 20099 | |
| 20100 | fn unionFieldIndex( |
| 20101 | sema: *Sema, |
| 20102 | block: *Block, |
| 20103 | unresolved_union_ty: Type, |
| 20104 | field_name: []const u8, |
| 20105 | field_src: LazySrcLoc, |
| 20106 | ) !u32 { |
| 20107 | const union_ty = try sema.resolveTypeFields(block, field_src, unresolved_union_ty); |
| 20108 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 20109 | const field_index_usize = union_obj.fields.getIndex(field_name) orelse |
| 20110 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| 20111 | return @intCast(u32, field_index_usize); |
| 20112 | } |