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