| ... | @@ -3773,6 +3773,7 @@ fn validateStructInit( | ... | @@ -3773,6 +3773,7 @@ fn validateStructInit( |
| 3773 | } | 3773 | } |
| 3774 | | 3774 | |
| 3775 | var root_msg: ?*Module.ErrorMsg = null; | 3775 | var root_msg: ?*Module.ErrorMsg = null; |
| | 3776 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 3776 | | 3777 | |
| 3777 | const struct_ptr = try sema.resolveInst(struct_ptr_zir_ref); | 3778 | const struct_ptr = try sema.resolveInst(struct_ptr_zir_ref); |
| 3778 | if ((is_comptime or block.is_comptime) and | 3779 | if ((is_comptime or block.is_comptime) and |
| ... | @@ -3948,6 +3949,7 @@ fn validateStructInit( | ... | @@ -3948,6 +3949,7 @@ fn validateStructInit( |
| 3948 | } | 3949 | } |
| 3949 | | 3950 | |
| 3950 | if (root_msg) |msg| { | 3951 | if (root_msg) |msg| { |
| | 3952 | root_msg = null; |
| 3951 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | 3953 | if (struct_ty.castTag(.@"struct")) |struct_obj| { |
| 3952 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); | 3954 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); |
| 3953 | defer gpa.free(fqn); | 3955 | defer gpa.free(fqn); |
| ... | @@ -4006,6 +4008,8 @@ fn zirValidateArrayInit( | ... | @@ -4006,6 +4008,8 @@ fn zirValidateArrayInit( |
| 4006 | if (instrs.len != array_len and array_ty.isTuple()) { | 4008 | if (instrs.len != array_len and array_ty.isTuple()) { |
| 4007 | const struct_obj = array_ty.castTag(.tuple).?.data; | 4009 | const struct_obj = array_ty.castTag(.tuple).?.data; |
| 4008 | var root_msg: ?*Module.ErrorMsg = null; | 4010 | var root_msg: ?*Module.ErrorMsg = null; |
| | 4011 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| | 4012 | |
| 4009 | for (struct_obj.values) |default_val, i| { | 4013 | for (struct_obj.values) |default_val, i| { |
| 4010 | if (i < instrs.len) continue; | 4014 | if (i < instrs.len) continue; |
| 4011 | | 4015 | |
| ... | @@ -4020,6 +4024,7 @@ fn zirValidateArrayInit( | ... | @@ -4020,6 +4024,7 @@ fn zirValidateArrayInit( |
| 4020 | } | 4024 | } |
| 4021 | | 4025 | |
| 4022 | if (root_msg) |msg| { | 4026 | if (root_msg) |msg| { |
| | 4027 | root_msg = null; |
| 4023 | return sema.failWithOwnedErrorMsg(msg); | 4028 | return sema.failWithOwnedErrorMsg(msg); |
| 4024 | } | 4029 | } |
| 4025 | } | 4030 | } |
| ... | @@ -6702,8 +6707,13 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -6702,8 +6707,13 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 6702 | defer tracy.end(); | 6707 | defer tracy.end(); |
| 6703 | | 6708 | |
| 6704 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 6709 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 6705 | const src = inst_data.src(); | 6710 | const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; |
| 6706 | const child_type = try sema.resolveType(block, src, inst_data.operand); | 6711 | const child_type = try sema.resolveType(block, operand_src, inst_data.operand); |
| | 6712 | if (child_type.zigTypeTag() == .Opaque) { |
| | 6713 | return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(sema.mod)}); |
| | 6714 | } else if (child_type.zigTypeTag() == .Null) { |
| | 6715 | return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(sema.mod)}); |
| | 6716 | } |
| 6707 | const opt_type = try Type.optional(sema.arena, child_type); | 6717 | const opt_type = try Type.optional(sema.arena, child_type); |
| 6708 | | 6718 | |
| 6709 | return sema.addType(opt_type); | 6719 | return sema.addType(opt_type); |
| ... | @@ -6802,6 +6812,15 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -6802,6 +6812,15 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 6802 | error_set.fmt(sema.mod), | 6812 | error_set.fmt(sema.mod), |
| 6803 | }); | 6813 | }); |
| 6804 | } | 6814 | } |
| | 6815 | if (payload.zigTypeTag() == .Opaque) { |
| | 6816 | return sema.fail(block, rhs_src, "error union with payload of opaque type '{}' not allowed", .{ |
| | 6817 | payload.fmt(sema.mod), |
| | 6818 | }); |
| | 6819 | } else if (payload.zigTypeTag() == .ErrorSet) { |
| | 6820 | return sema.fail(block, rhs_src, "error union with payload of error set type '{}' not allowed", .{ |
| | 6821 | payload.fmt(sema.mod), |
| | 6822 | }); |
| | 6823 | } |
| 6805 | const err_union_ty = try Type.errorUnion(sema.arena, error_set, payload, sema.mod); | 6824 | const err_union_ty = try Type.errorUnion(sema.arena, error_set, payload, sema.mod); |
| 6806 | return sema.addType(err_union_ty); | 6825 | return sema.addType(err_union_ty); |
| 6807 | } | 6826 | } |
| ... | @@ -8968,12 +8987,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -8968,12 +8987,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8968 | }, | 8987 | }, |
| 8969 | }; | 8988 | }; |
| 8970 | | 8989 | |
| 8971 | const union_originally = blk: { | 8990 | const maybe_union_ty = blk: { |
| 8972 | const zir_data = sema.code.instructions.items(.data); | 8991 | const zir_data = sema.code.instructions.items(.data); |
| 8973 | const cond_index = Zir.refToIndex(extra.data.operand).?; | 8992 | const cond_index = Zir.refToIndex(extra.data.operand).?; |
| 8974 | const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable; | 8993 | const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable; |
| 8975 | break :blk sema.typeOf(raw_operand).zigTypeTag() == .Union; | 8994 | break :blk sema.typeOf(raw_operand); |
| 8976 | }; | 8995 | }; |
| | 8996 | const union_originally = maybe_union_ty.zigTypeTag() == .Union; |
| | 8997 | var seen_union_fields: []?Module.SwitchProngSrc = &.{}; |
| | 8998 | defer gpa.free(seen_union_fields); |
| | 8999 | |
| | 9000 | var empty_enum = false; |
| 8977 | | 9001 | |
| 8978 | const operand_ty = sema.typeOf(operand); | 9002 | const operand_ty = sema.typeOf(operand); |
| 8979 | | 9003 | |
| ... | @@ -9008,7 +9032,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -9008,7 +9032,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 9008 | .Union => unreachable, // handled in zirSwitchCond | 9032 | .Union => unreachable, // handled in zirSwitchCond |
| 9009 | .Enum => { | 9033 | .Enum => { |
| 9010 | var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount()); | 9034 | var seen_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount()); |
| 9011 | defer gpa.free(seen_fields); | 9035 | empty_enum = seen_fields.len == 0 and !operand_ty.isNonexhaustiveEnum(); |
| | 9036 | defer if (!union_originally) gpa.free(seen_fields); |
| | 9037 | if (union_originally) seen_union_fields = seen_fields; |
| 9012 | mem.set(?Module.SwitchProngSrc, seen_fields, null); | 9038 | mem.set(?Module.SwitchProngSrc, seen_fields, null); |
| 9013 | | 9039 | |
| 9014 | // This is used for non-exhaustive enum values that do not correspond to any tags. | 9040 | // This is used for non-exhaustive enum values that do not correspond to any tags. |
| ... | @@ -9602,6 +9628,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -9602,6 +9628,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 9602 | } | 9628 | } |
| 9603 | | 9629 | |
| 9604 | if (scalar_cases_len + multi_cases_len == 0) { | 9630 | if (scalar_cases_len + multi_cases_len == 0) { |
| | 9631 | if (empty_enum) { |
| | 9632 | return Air.Inst.Ref.void_value; |
| | 9633 | } |
| 9605 | if (special_prong == .none) { | 9634 | if (special_prong == .none) { |
| 9606 | return sema.fail(block, src, "switch must handle all possibilities", .{}); | 9635 | return sema.fail(block, src, "switch must handle all possibilities", .{}); |
| 9607 | } | 9636 | } |
| ... | @@ -9641,18 +9670,28 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -9641,18 +9670,28 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 9641 | const item = try sema.resolveInst(item_ref); | 9670 | const item = try sema.resolveInst(item_ref); |
| 9642 | // `item` is already guaranteed to be constant known. | 9671 | // `item` is already guaranteed to be constant known. |
| 9643 | | 9672 | |
| 9644 | _ = sema.analyzeBodyInner(&case_block, body) catch |err| switch (err) { | 9673 | const analyze_body = if (union_originally) blk: { |
| 9645 | error.ComptimeBreak => { | 9674 | const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable; |
| 9646 | const zir_datas = sema.code.instructions.items(.data); | 9675 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); |
| 9647 | const break_data = zir_datas[sema.comptime_break_inst].@"break"; | 9676 | break :blk field_ty.zigTypeTag() != .NoReturn; |
| 9648 | try sema.addRuntimeBreak(&case_block, .{ | 9677 | } else true; |
| 9649 | .block_inst = break_data.block_inst, | 9678 | |
| 9650 | .operand = break_data.operand, | 9679 | if (analyze_body) { |
| 9651 | .inst = sema.comptime_break_inst, | 9680 | _ = sema.analyzeBodyInner(&case_block, body) catch |err| switch (err) { |
| 9652 | }); | 9681 | error.ComptimeBreak => { |
| 9653 | }, | 9682 | const zir_datas = sema.code.instructions.items(.data); |
| 9654 | else => |e| return e, | 9683 | const break_data = zir_datas[sema.comptime_break_inst].@"break"; |
| 9655 | }; | 9684 | try sema.addRuntimeBreak(&case_block, .{ |
| | 9685 | .block_inst = break_data.block_inst, |
| | 9686 | .operand = break_data.operand, |
| | 9687 | .inst = sema.comptime_break_inst, |
| | 9688 | }); |
| | 9689 | }, |
| | 9690 | else => |e| return e, |
| | 9691 | }; |
| | 9692 | } else { |
| | 9693 | _ = try case_block.addNoOp(.unreach); |
| | 9694 | } |
| 9656 | | 9695 | |
| 9657 | try wip_captures.finalize(); | 9696 | try wip_captures.finalize(); |
| 9658 | | 9697 | |
| ... | @@ -9693,20 +9732,34 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -9693,20 +9732,34 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 9693 | if (ranges_len == 0) { | 9732 | if (ranges_len == 0) { |
| 9694 | cases_len += 1; | 9733 | cases_len += 1; |
| 9695 | | 9734 | |
| | 9735 | const analyze_body = if (union_originally) |
| | 9736 | for (items) |item_ref| { |
| | 9737 | const item = try sema.resolveInst(item_ref); |
| | 9738 | const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable; |
| | 9739 | const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod); |
| | 9740 | if (field_ty.zigTypeTag() != .NoReturn) break true; |
| | 9741 | } else false |
| | 9742 | else |
| | 9743 | true; |
| | 9744 | |
| 9696 | const body = sema.code.extra[extra_index..][0..body_len]; | 9745 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 9697 | extra_index += body_len; | 9746 | extra_index += body_len; |
| 9698 | _ = sema.analyzeBodyInner(&case_block, body) catch |err| switch (err) { | 9747 | if (analyze_body) { |
| 9699 | error.ComptimeBreak => { | 9748 | _ = sema.analyzeBodyInner(&case_block, body) catch |err| switch (err) { |
| 9700 | const zir_datas = sema.code.instructions.items(.data); | 9749 | error.ComptimeBreak => { |
| 9701 | const break_data = zir_datas[sema.comptime_break_inst].@"break"; | 9750 | const zir_datas = sema.code.instructions.items(.data); |
| 9702 | try sema.addRuntimeBreak(&case_block, .{ | 9751 | const break_data = zir_datas[sema.comptime_break_inst].@"break"; |
| 9703 | .block_inst = break_data.block_inst, | 9752 | try sema.addRuntimeBreak(&case_block, .{ |
| 9704 | .operand = break_data.operand, | 9753 | .block_inst = break_data.block_inst, |
| 9705 | .inst = sema.comptime_break_inst, | 9754 | .operand = break_data.operand, |
| 9706 | }); | 9755 | .inst = sema.comptime_break_inst, |
| 9707 | }, | 9756 | }); |
| 9708 | else => |e| return e, | 9757 | }, |
| 9709 | }; | 9758 | else => |e| return e, |
| | 9759 | }; |
| | 9760 | } else { |
| | 9761 | _ = try case_block.addNoOp(.unreach); |
| | 9762 | } |
| 9710 | | 9763 | |
| 9711 | try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + | 9764 | try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + |
| 9712 | case_block.instructions.items.len); | 9765 | case_block.instructions.items.len); |
| ... | @@ -9828,7 +9881,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -9828,7 +9881,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 9828 | case_block.instructions.shrinkRetainingCapacity(0); | 9881 | case_block.instructions.shrinkRetainingCapacity(0); |
| 9829 | case_block.wip_capture_scope = wip_captures.scope; | 9882 | case_block.wip_capture_scope = wip_captures.scope; |
| 9830 | | 9883 | |
| 9831 | if (special.body.len != 0) { | 9884 | const analyze_body = if (union_originally) |
| | 9885 | for (seen_union_fields) |seen_field, index| { |
| | 9886 | if (seen_field != null) continue; |
| | 9887 | const union_obj = maybe_union_ty.cast(Type.Payload.Union).?.data; |
| | 9888 | const field_ty = union_obj.fields.values()[index].ty; |
| | 9889 | if (field_ty.zigTypeTag() != .NoReturn) break true; |
| | 9890 | } else false |
| | 9891 | else |
| | 9892 | true; |
| | 9893 | |
| | 9894 | if (special.body.len != 0 and analyze_body) { |
| 9832 | _ = sema.analyzeBodyInner(&case_block, special.body) catch |err| switch (err) { | 9895 | _ = sema.analyzeBodyInner(&case_block, special.body) catch |err| switch (err) { |
| 9833 | error.ComptimeBreak => { | 9896 | error.ComptimeBreak => { |
| 9834 | const zir_datas = sema.code.instructions.items(.data); | 9897 | const zir_datas = sema.code.instructions.items(.data); |
| ... | @@ -13244,6 +13307,14 @@ fn analyzeCmpUnionTag( | ... | @@ -13244,6 +13307,14 @@ fn analyzeCmpUnionTag( |
| 13244 | const coerced_tag = try sema.coerce(block, union_tag_ty, tag, tag_src); | 13307 | const coerced_tag = try sema.coerce(block, union_tag_ty, tag, tag_src); |
| 13245 | const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src); | 13308 | const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src); |
| 13246 | | 13309 | |
| | 13310 | if (try sema.resolveMaybeUndefVal(block, tag_src, coerced_tag)) |enum_val| { |
| | 13311 | if (enum_val.isUndef()) return sema.addConstUndef(Type.bool); |
| | 13312 | const field_ty = union_ty.unionFieldType(enum_val, sema.mod); |
| | 13313 | if (field_ty.zigTypeTag() == .NoReturn) { |
| | 13314 | return Air.Inst.Ref.bool_false; |
| | 13315 | } |
| | 13316 | } |
| | 13317 | |
| 13247 | return sema.cmpSelf(block, src, coerced_union, coerced_tag, op, un_src, tag_src); | 13318 | return sema.cmpSelf(block, src, coerced_union, coerced_tag, op, un_src, tag_src); |
| 13248 | } | 13319 | } |
| 13249 | | 13320 | |
| ... | @@ -15598,6 +15669,8 @@ fn finishStructInit( | ... | @@ -15598,6 +15669,8 @@ fn finishStructInit( |
| 15598 | const gpa = sema.gpa; | 15669 | const gpa = sema.gpa; |
| 15599 | | 15670 | |
| 15600 | var root_msg: ?*Module.ErrorMsg = null; | 15671 | var root_msg: ?*Module.ErrorMsg = null; |
| | 15672 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| | 15673 | |
| 15601 | if (struct_ty.isAnonStruct()) { | 15674 | if (struct_ty.isAnonStruct()) { |
| 15602 | const struct_obj = struct_ty.castTag(.anon_struct).?.data; | 15675 | const struct_obj = struct_ty.castTag(.anon_struct).?.data; |
| 15603 | for (struct_obj.values) |default_val, i| { | 15676 | for (struct_obj.values) |default_val, i| { |
| ... | @@ -15653,6 +15726,7 @@ fn finishStructInit( | ... | @@ -15653,6 +15726,7 @@ fn finishStructInit( |
| 15653 | } | 15726 | } |
| 15654 | | 15727 | |
| 15655 | if (root_msg) |msg| { | 15728 | if (root_msg) |msg| { |
| | 15729 | root_msg = null; |
| 15656 | if (struct_ty.castTag(.@"struct")) |struct_obj| { | 15730 | if (struct_ty.castTag(.@"struct")) |struct_obj| { |
| 15657 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); | 15731 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); |
| 15658 | defer gpa.free(fqn); | 15732 | defer gpa.free(fqn); |
| ... | @@ -16655,43 +16729,39 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -16655,43 +16729,39 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 16655 | | 16729 | |
| 16656 | // Fields | 16730 | // Fields |
| 16657 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); | 16731 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); |
| 16658 | if (fields_len > 0) { | 16732 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 16659 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); | 16733 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ |
| 16660 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ | 16734 | .ty = enum_obj.tag_ty, |
| 16661 | .ty = enum_obj.tag_ty, | 16735 | .mod = mod, |
| 16662 | .mod = mod, | 16736 | }); |
| 16663 | }); | | |
| 16664 | | | |
| 16665 | var i: usize = 0; | | |
| 16666 | while (i < fields_len) : (i += 1) { | | |
| 16667 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); | | |
| 16668 | const field_struct_val = elem_val.castTag(.aggregate).?.data; | | |
| 16669 | // TODO use reflection instead of magic numbers here | | |
| 16670 | // name: []const u8 | | |
| 16671 | const name_val = field_struct_val[0]; | | |
| 16672 | // value: comptime_int | | |
| 16673 | const value_val = field_struct_val[1]; | | |
| 16674 | | | |
| 16675 | const field_name = try name_val.toAllocatedBytes( | | |
| 16676 | Type.initTag(.const_slice_u8), | | |
| 16677 | new_decl_arena_allocator, | | |
| 16678 | sema.mod, | | |
| 16679 | ); | | |
| 16680 | | 16737 | |
| 16681 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); | 16738 | var i: usize = 0; |
| 16682 | if (gop.found_existing) { | 16739 | while (i < fields_len) : (i += 1) { |
| 16683 | // TODO: better source location | 16740 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); |
| 16684 | return sema.fail(block, src, "duplicate enum tag {s}", .{field_name}); | 16741 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 16685 | } | 16742 | // TODO use reflection instead of magic numbers here |
| | 16743 | // name: []const u8 |
| | 16744 | const name_val = field_struct_val[0]; |
| | 16745 | // value: comptime_int |
| | 16746 | const value_val = field_struct_val[1]; |
| | 16747 | |
| | 16748 | const field_name = try name_val.toAllocatedBytes( |
| | 16749 | Type.initTag(.const_slice_u8), |
| | 16750 | new_decl_arena_allocator, |
| | 16751 | sema.mod, |
| | 16752 | ); |
| 16686 | | 16753 | |
| 16687 | const copied_tag_val = try value_val.copy(new_decl_arena_allocator); | 16754 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| 16688 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ | 16755 | if (gop.found_existing) { |
| 16689 | .ty = enum_obj.tag_ty, | 16756 | // TODO: better source location |
| 16690 | .mod = mod, | 16757 | return sema.fail(block, src, "duplicate enum tag {s}", .{field_name}); |
| 16691 | }); | | |
| 16692 | } | 16758 | } |
| 16693 | } else { | 16759 | |
| 16694 | return sema.fail(block, src, "enums must have at least one field", .{}); | 16760 | const copied_tag_val = try value_val.copy(new_decl_arena_allocator); |
| | 16761 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ |
| | 16762 | .ty = enum_obj.tag_ty, |
| | 16763 | .mod = mod, |
| | 16764 | }); |
| 16695 | } | 16765 | } |
| 16696 | | 16766 | |
| 16697 | try new_decl.finalizeNewArena(&new_decl_arena); | 16767 | try new_decl.finalizeNewArena(&new_decl_arena); |
| ... | @@ -16816,58 +16886,54 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -16816,58 +16886,54 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 16816 | } | 16886 | } |
| 16817 | | 16887 | |
| 16818 | // Fields | 16888 | // Fields |
| 16819 | if (fields_len > 0) { | 16889 | try union_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 16820 | try union_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); | | |
| 16821 | | 16890 | |
| 16822 | var i: usize = 0; | 16891 | var i: usize = 0; |
| 16823 | while (i < fields_len) : (i += 1) { | 16892 | while (i < fields_len) : (i += 1) { |
| 16824 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); | 16893 | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); |
| 16825 | const field_struct_val = elem_val.castTag(.aggregate).?.data; | 16894 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 16826 | // TODO use reflection instead of magic numbers here | 16895 | // TODO use reflection instead of magic numbers here |
| 16827 | // name: []const u8 | 16896 | // name: []const u8 |
| 16828 | const name_val = field_struct_val[0]; | 16897 | const name_val = field_struct_val[0]; |
| 16829 | // field_type: type, | 16898 | // field_type: type, |
| 16830 | const field_type_val = field_struct_val[1]; | 16899 | const field_type_val = field_struct_val[1]; |
| 16831 | // alignment: comptime_int, | 16900 | // alignment: comptime_int, |
| 16832 | const alignment_val = field_struct_val[2]; | 16901 | const alignment_val = field_struct_val[2]; |
| 16833 | | | |
| 16834 | const field_name = try name_val.toAllocatedBytes( | | |
| 16835 | Type.initTag(.const_slice_u8), | | |
| 16836 | new_decl_arena_allocator, | | |
| 16837 | sema.mod, | | |
| 16838 | ); | | |
| 16839 | | 16902 | |
| 16840 | if (enum_field_names) |set| { | 16903 | const field_name = try name_val.toAllocatedBytes( |
| 16841 | set.putAssumeCapacity(field_name, {}); | 16904 | Type.initTag(.const_slice_u8), |
| 16842 | } | 16905 | new_decl_arena_allocator, |
| | 16906 | sema.mod, |
| | 16907 | ); |
| 16843 | | 16908 | |
| 16844 | if (tag_ty_field_names) |*names| { | 16909 | if (enum_field_names) |set| { |
| 16845 | const enum_has_field = names.orderedRemove(field_name); | 16910 | set.putAssumeCapacity(field_name, {}); |
| 16846 | if (!enum_has_field) { | 16911 | } |
| 16847 | const msg = msg: { | | |
| 16848 | const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) }); | | |
| 16849 | errdefer msg.destroy(sema.gpa); | | |
| 16850 | try sema.addDeclaredHereNote(msg, union_obj.tag_ty); | | |
| 16851 | break :msg msg; | | |
| 16852 | }; | | |
| 16853 | return sema.failWithOwnedErrorMsg(msg); | | |
| 16854 | } | | |
| 16855 | } | | |
| 16856 | | 16912 | |
| 16857 | const gop = union_obj.fields.getOrPutAssumeCapacity(field_name); | 16913 | if (tag_ty_field_names) |*names| { |
| 16858 | if (gop.found_existing) { | 16914 | const enum_has_field = names.orderedRemove(field_name); |
| 16859 | // TODO: better source location | 16915 | if (!enum_has_field) { |
| 16860 | return sema.fail(block, src, "duplicate union field {s}", .{field_name}); | 16916 | const msg = msg: { |
| | 16917 | const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) }); |
| | 16918 | errdefer msg.destroy(sema.gpa); |
| | 16919 | try sema.addDeclaredHereNote(msg, union_obj.tag_ty); |
| | 16920 | break :msg msg; |
| | 16921 | }; |
| | 16922 | return sema.failWithOwnedErrorMsg(msg); |
| 16861 | } | 16923 | } |
| | 16924 | } |
| 16862 | | 16925 | |
| 16863 | var buffer: Value.ToTypeBuffer = undefined; | 16926 | const gop = union_obj.fields.getOrPutAssumeCapacity(field_name); |
| 16864 | gop.value_ptr.* = .{ | 16927 | if (gop.found_existing) { |
| 16865 | .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator), | 16928 | // TODO: better source location |
| 16866 | .abi_align = @intCast(u32, alignment_val.toUnsignedInt(target)), | 16929 | return sema.fail(block, src, "duplicate union field {s}", .{field_name}); |
| 16867 | }; | | |
| 16868 | } | 16930 | } |
| 16869 | } else { | 16931 | |
| 16870 | return sema.fail(block, src, "unions must have at least one field", .{}); | 16932 | var buffer: Value.ToTypeBuffer = undefined; |
| | 16933 | gop.value_ptr.* = .{ |
| | 16934 | .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator), |
| | 16935 | .abi_align = @intCast(u32, alignment_val.toUnsignedInt(target)), |
| | 16936 | }; |
| 16871 | } | 16937 | } |
| 16872 | | 16938 | |
| 16873 | if (tag_ty_field_names) |names| { | 16939 | if (tag_ty_field_names) |names| { |
| ... | @@ -21701,6 +21767,18 @@ fn unionFieldPtr( | ... | @@ -21701,6 +21767,18 @@ fn unionFieldPtr( |
| 21701 | .@"addrspace" = union_ptr_ty.ptrAddressSpace(), | 21767 | .@"addrspace" = union_ptr_ty.ptrAddressSpace(), |
| 21702 | }); | 21768 | }); |
| 21703 | | 21769 | |
| | 21770 | if (initializing and field.ty.zigTypeTag() == .NoReturn) { |
| | 21771 | const msg = msg: { |
| | 21772 | const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{}); |
| | 21773 | errdefer msg.destroy(sema.gpa); |
| | 21774 | |
| | 21775 | try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' declared here", .{field_name}); |
| | 21776 | try sema.addDeclaredHereNote(msg, union_ty); |
| | 21777 | break :msg msg; |
| | 21778 | }; |
| | 21779 | return sema.failWithOwnedErrorMsg(msg); |
| | 21780 | } |
| | 21781 | |
| 21704 | if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| ct: { | 21782 | if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| ct: { |
| 21705 | switch (union_obj.layout) { | 21783 | switch (union_obj.layout) { |
| 21706 | .Auto => if (!initializing) { | 21784 | .Auto => if (!initializing) { |
| ... | @@ -21753,6 +21831,10 @@ fn unionFieldPtr( | ... | @@ -21753,6 +21831,10 @@ fn unionFieldPtr( |
| 21753 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 21831 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 21754 | try sema.addSafetyCheck(block, ok, .inactive_union_field); | 21832 | try sema.addSafetyCheck(block, ok, .inactive_union_field); |
| 21755 | } | 21833 | } |
| | 21834 | if (field.ty.zigTypeTag() == .NoReturn) { |
| | 21835 | _ = try block.addNoOp(.unreach); |
| | 21836 | return Air.Inst.Ref.unreachable_value; |
| | 21837 | } |
| 21756 | return block.addStructFieldPtr(union_ptr, field_index, ptr_field_ty); | 21838 | return block.addStructFieldPtr(union_ptr, field_index, ptr_field_ty); |
| 21757 | } | 21839 | } |
| 21758 | | 21840 | |
| ... | @@ -21821,6 +21903,10 @@ fn unionFieldVal( | ... | @@ -21821,6 +21903,10 @@ fn unionFieldVal( |
| 21821 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 21903 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 21822 | try sema.addSafetyCheck(block, ok, .inactive_union_field); | 21904 | try sema.addSafetyCheck(block, ok, .inactive_union_field); |
| 21823 | } | 21905 | } |
| | 21906 | if (field.ty.zigTypeTag() == .NoReturn) { |
| | 21907 | _ = try block.addNoOp(.unreach); |
| | 21908 | return Air.Inst.Ref.unreachable_value; |
| | 21909 | } |
| 21824 | return block.addStructFieldVal(union_byval, field_index, field.ty); | 21910 | return block.addStructFieldVal(union_byval, field_index, field.ty); |
| 21825 | } | 21911 | } |
| 21826 | | 21912 | |
| ... | @@ -25021,6 +25107,18 @@ fn coerceEnumToUnion( | ... | @@ -25021,6 +25107,18 @@ fn coerceEnumToUnion( |
| 25021 | }; | 25107 | }; |
| 25022 | const field = union_obj.fields.values()[field_index]; | 25108 | const field = union_obj.fields.values()[field_index]; |
| 25023 | const field_ty = try sema.resolveTypeFields(block, inst_src, field.ty); | 25109 | const field_ty = try sema.resolveTypeFields(block, inst_src, field.ty); |
| | 25110 | if (field_ty.zigTypeTag() == .NoReturn) { |
| | 25111 | const msg = msg: { |
| | 25112 | const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{}); |
| | 25113 | errdefer msg.destroy(sema.gpa); |
| | 25114 | |
| | 25115 | const field_name = union_obj.fields.keys()[field_index]; |
| | 25116 | try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' declared here", .{field_name}); |
| | 25117 | try sema.addDeclaredHereNote(msg, union_ty); |
| | 25118 | break :msg msg; |
| | 25119 | }; |
| | 25120 | return sema.failWithOwnedErrorMsg(msg); |
| | 25121 | } |
| 25024 | const opv = (try sema.typeHasOnePossibleValue(block, inst_src, field_ty)) orelse { | 25122 | const opv = (try sema.typeHasOnePossibleValue(block, inst_src, field_ty)) orelse { |
| 25025 | const msg = msg: { | 25123 | const msg = msg: { |
| 25026 | const field_name = union_obj.fields.keys()[field_index]; | 25124 | const field_name = union_obj.fields.keys()[field_index]; |
| ... | @@ -25056,13 +25154,37 @@ fn coerceEnumToUnion( | ... | @@ -25056,13 +25154,37 @@ fn coerceEnumToUnion( |
| 25056 | return sema.failWithOwnedErrorMsg(msg); | 25154 | return sema.failWithOwnedErrorMsg(msg); |
| 25057 | } | 25155 | } |
| 25058 | | 25156 | |
| | 25157 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| | 25158 | { |
| | 25159 | var msg: ?*Module.ErrorMsg = null; |
| | 25160 | errdefer if (msg) |some| some.destroy(sema.gpa); |
| | 25161 | |
| | 25162 | for (union_obj.fields.values()) |field, i| { |
| | 25163 | if (field.ty.zigTypeTag() == .NoReturn) { |
| | 25164 | const err_msg = msg orelse try sema.errMsg( |
| | 25165 | block, |
| | 25166 | inst_src, |
| | 25167 | "runtime coercion from enum '{}' to union '{}' which has a 'noreturn' field", |
| | 25168 | .{ tag_ty.fmt(sema.mod), union_ty.fmt(sema.mod) }, |
| | 25169 | ); |
| | 25170 | msg = err_msg; |
| | 25171 | |
| | 25172 | try sema.addFieldErrNote(block, union_ty, i, err_msg, "'noreturn' field here", .{}); |
| | 25173 | } |
| | 25174 | } |
| | 25175 | if (msg) |some| { |
| | 25176 | msg = null; |
| | 25177 | try sema.addDeclaredHereNote(some, union_ty); |
| | 25178 | return sema.failWithOwnedErrorMsg(some); |
| | 25179 | } |
| | 25180 | } |
| | 25181 | |
| 25059 | // If the union has all fields 0 bits, the union value is just the enum value. | 25182 | // If the union has all fields 0 bits, the union value is just the enum value. |
| 25060 | if (union_ty.unionHasAllZeroBitFieldTypes()) { | 25183 | if (union_ty.unionHasAllZeroBitFieldTypes()) { |
| 25061 | return block.addBitCast(union_ty, enum_tag); | 25184 | return block.addBitCast(union_ty, enum_tag); |
| 25062 | } | 25185 | } |
| 25063 | | 25186 | |
| 25064 | const msg = msg: { | 25187 | const msg = msg: { |
| 25065 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | | |
| 25066 | const msg = try sema.errMsg( | 25188 | const msg = try sema.errMsg( |
| 25067 | block, | 25189 | block, |
| 25068 | inst_src, | 25190 | inst_src, |
| ... | @@ -25073,11 +25195,11 @@ fn coerceEnumToUnion( | ... | @@ -25073,11 +25195,11 @@ fn coerceEnumToUnion( |
| 25073 | | 25195 | |
| 25074 | var it = union_obj.fields.iterator(); | 25196 | var it = union_obj.fields.iterator(); |
| 25075 | var field_index: usize = 0; | 25197 | var field_index: usize = 0; |
| 25076 | while (it.next()) |field| { | 25198 | while (it.next()) |field| : (field_index += 1) { |
| 25077 | const field_name = field.key_ptr.*; | 25199 | const field_name = field.key_ptr.*; |
| 25078 | const field_ty = field.value_ptr.ty; | 25200 | const field_ty = field.value_ptr.ty; |
| | 25201 | if (!field_ty.hasRuntimeBits()) continue; |
| 25079 | try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) }); | 25202 | try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) }); |
| 25080 | field_index += 1; | | |
| 25081 | } | 25203 | } |
| 25082 | try sema.addDeclaredHereNote(msg, union_ty); | 25204 | try sema.addDeclaredHereNote(msg, union_ty); |
| 25083 | break :msg msg; | 25205 | break :msg msg; |
| ... | @@ -25380,6 +25502,7 @@ fn coerceTupleToStruct( | ... | @@ -25380,6 +25502,7 @@ fn coerceTupleToStruct( |
| 25380 | | 25502 | |
| 25381 | // Populate default field values and report errors for missing fields. | 25503 | // Populate default field values and report errors for missing fields. |
| 25382 | var root_msg: ?*Module.ErrorMsg = null; | 25504 | var root_msg: ?*Module.ErrorMsg = null; |
| | 25505 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 25383 | | 25506 | |
| 25384 | for (field_refs) |*field_ref, i| { | 25507 | for (field_refs) |*field_ref, i| { |
| 25385 | if (field_ref.* != .none) continue; | 25508 | if (field_ref.* != .none) continue; |
| ... | @@ -25405,6 +25528,7 @@ fn coerceTupleToStruct( | ... | @@ -25405,6 +25528,7 @@ fn coerceTupleToStruct( |
| 25405 | } | 25528 | } |
| 25406 | | 25529 | |
| 25407 | if (root_msg) |msg| { | 25530 | if (root_msg) |msg| { |
| | 25531 | root_msg = null; |
| 25408 | try sema.addDeclaredHereNote(msg, struct_ty); | 25532 | try sema.addDeclaredHereNote(msg, struct_ty); |
| 25409 | return sema.failWithOwnedErrorMsg(msg); | 25533 | return sema.failWithOwnedErrorMsg(msg); |
| 25410 | } | 25534 | } |
| ... | @@ -25474,6 +25598,7 @@ fn coerceTupleToTuple( | ... | @@ -25474,6 +25598,7 @@ fn coerceTupleToTuple( |
| 25474 | | 25598 | |
| 25475 | // Populate default field values and report errors for missing fields. | 25599 | // Populate default field values and report errors for missing fields. |
| 25476 | var root_msg: ?*Module.ErrorMsg = null; | 25600 | var root_msg: ?*Module.ErrorMsg = null; |
| | 25601 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 25477 | | 25602 | |
| 25478 | for (field_refs) |*field_ref, i| { | 25603 | for (field_refs) |*field_ref, i| { |
| 25479 | if (field_ref.* != .none) continue; | 25604 | if (field_ref.* != .none) continue; |
| ... | @@ -25509,6 +25634,7 @@ fn coerceTupleToTuple( | ... | @@ -25509,6 +25634,7 @@ fn coerceTupleToTuple( |
| 25509 | } | 25634 | } |
| 25510 | | 25635 | |
| 25511 | if (root_msg) |msg| { | 25636 | if (root_msg) |msg| { |
| | 25637 | root_msg = null; |
| 25512 | try sema.addDeclaredHereNote(msg, tuple_ty); | 25638 | try sema.addDeclaredHereNote(msg, tuple_ty); |
| 25513 | return sema.failWithOwnedErrorMsg(msg); | 25639 | return sema.failWithOwnedErrorMsg(msg); |
| 25514 | } | 25640 | } |
| ... | @@ -25747,6 +25873,12 @@ fn analyzeIsNull( | ... | @@ -25747,6 +25873,12 @@ fn analyzeIsNull( |
| 25747 | return Air.Inst.Ref.bool_false; | 25873 | return Air.Inst.Ref.bool_false; |
| 25748 | } | 25874 | } |
| 25749 | } | 25875 | } |
| | 25876 | |
| | 25877 | const operand_ty = sema.typeOf(operand); |
| | 25878 | var buf: Type.Payload.ElemType = undefined; |
| | 25879 | if (operand_ty.zigTypeTag() == .Optional and operand_ty.optionalChild(&buf).zigTypeTag() == .NoReturn) { |
| | 25880 | return Air.Inst.Ref.bool_true; |
| | 25881 | } |
| 25750 | try sema.requireRuntimeBlock(block, src, null); | 25882 | try sema.requireRuntimeBlock(block, src, null); |
| 25751 | const air_tag: Air.Inst.Tag = if (invert_logic) .is_non_null else .is_null; | 25883 | const air_tag: Air.Inst.Tag = if (invert_logic) .is_non_null else .is_null; |
| 25752 | return block.addUnOp(air_tag, operand); | 25884 | return block.addUnOp(air_tag, operand); |
| ... | @@ -25785,6 +25917,11 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -25785,6 +25917,11 @@ fn analyzeIsNonErrComptimeOnly( |
| 25785 | if (ot == .ErrorSet) return Air.Inst.Ref.bool_false; | 25917 | if (ot == .ErrorSet) return Air.Inst.Ref.bool_false; |
| 25786 | assert(ot == .ErrorUnion); | 25918 | assert(ot == .ErrorUnion); |
| 25787 | | 25919 | |
| | 25920 | const payload_ty = operand_ty.errorUnionPayload(); |
| | 25921 | if (payload_ty.zigTypeTag() == .NoReturn) { |
| | 25922 | return Air.Inst.Ref.bool_false; |
| | 25923 | } |
| | 25924 | |
| 25788 | if (Air.refToIndex(operand)) |operand_inst| { | 25925 | if (Air.refToIndex(operand)) |operand_inst| { |
| 25789 | switch (sema.air_instructions.items(.tag)[operand_inst]) { | 25926 | switch (sema.air_instructions.items(.tag)[operand_inst]) { |
| 25790 | .wrap_errunion_payload => return Air.Inst.Ref.bool_true, | 25927 | .wrap_errunion_payload => return Air.Inst.Ref.bool_true, |
| ... | @@ -27922,6 +28059,18 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -27922,6 +28059,18 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 27922 | }; | 28059 | }; |
| 27923 | return sema.failWithOwnedErrorMsg(msg); | 28060 | return sema.failWithOwnedErrorMsg(msg); |
| 27924 | } | 28061 | } |
| | 28062 | if (field_ty.zigTypeTag() == .NoReturn) { |
| | 28063 | const msg = msg: { |
| | 28064 | const tree = try sema.getAstTree(&block_scope); |
| | 28065 | const field_src = enumFieldSrcLoc(decl, tree.*, 0, i); |
| | 28066 | const msg = try sema.errMsg(&block_scope, field_src, "struct fields cannot be 'noreturn'", .{}); |
| | 28067 | errdefer msg.destroy(sema.gpa); |
| | 28068 | |
| | 28069 | try sema.addDeclaredHereNote(msg, field_ty); |
| | 28070 | break :msg msg; |
| | 28071 | }; |
| | 28072 | return sema.failWithOwnedErrorMsg(msg); |
| | 28073 | } |
| 27925 | if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) { | 28074 | if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) { |
| 27926 | const msg = msg: { | 28075 | const msg = msg: { |
| 27927 | const tree = try sema.getAstTree(&block_scope); | 28076 | const tree = try sema.getAstTree(&block_scope); |
| ... | @@ -28028,10 +28177,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -28028,10 +28177,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 28028 | extra_index = decls_it.extra_index; | 28177 | extra_index = decls_it.extra_index; |
| 28029 | | 28178 | |
| 28030 | const body = zir.extra[extra_index..][0..body_len]; | 28179 | const body = zir.extra[extra_index..][0..body_len]; |
| 28031 | if (fields_len == 0) { | | |
| 28032 | assert(body.len == 0); | | |
| 28033 | return; | | |
| 28034 | } | | |
| 28035 | extra_index += body.len; | 28180 | extra_index += body.len; |
| 28036 | | 28181 | |
| 28037 | const decl = mod.declPtr(decl_index); | 28182 | const decl = mod.declPtr(decl_index); |
| ... | @@ -28119,6 +28264,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -28119,6 +28264,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 28119 | enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields; | 28264 | enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields; |
| 28120 | } | 28265 | } |
| 28121 | | 28266 | |
| | 28267 | if (fields_len == 0) { |
| | 28268 | return; |
| | 28269 | } |
| | 28270 | |
| 28122 | const bits_per_field = 4; | 28271 | const bits_per_field = 4; |
| 28123 | const fields_per_u32 = 32 / bits_per_field; | 28272 | const fields_per_u32 = 32 / bits_per_field; |
| 28124 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; | 28273 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; |
| ... | @@ -28654,7 +28803,9 @@ pub fn typeHasOnePossibleValue( | ... | @@ -28654,7 +28803,9 @@ pub fn typeHasOnePossibleValue( |
| 28654 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; | 28803 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |
| 28655 | const tag_val = (try sema.typeHasOnePossibleValue(block, src, union_obj.tag_ty)) orelse | 28804 | const tag_val = (try sema.typeHasOnePossibleValue(block, src, union_obj.tag_ty)) orelse |
| 28656 | return null; | 28805 | return null; |
| 28657 | const only_field = union_obj.fields.values()[0]; | 28806 | const fields = union_obj.fields.values(); |
| | 28807 | if (fields.len == 0) return Value.initTag(.empty_struct_value); |
| | 28808 | const only_field = fields[0]; |
| 28658 | if (only_field.ty.eql(resolved_ty, sema.mod)) { | 28809 | if (only_field.ty.eql(resolved_ty, sema.mod)) { |
| 28659 | const msg = try Module.ErrorMsg.create( | 28810 | const msg = try Module.ErrorMsg.create( |
| 28660 | sema.gpa, | 28811 | sema.gpa, |
| ... | @@ -28733,6 +28884,16 @@ fn enumFieldSrcLoc( | ... | @@ -28733,6 +28884,16 @@ fn enumFieldSrcLoc( |
| 28733 | .container_decl_arg_trailing, | 28884 | .container_decl_arg_trailing, |
| 28734 | => tree.containerDeclArg(enum_node), | 28885 | => tree.containerDeclArg(enum_node), |
| 28735 | | 28886 | |
| | 28887 | .tagged_union, |
| | 28888 | .tagged_union_trailing, |
| | 28889 | => tree.taggedUnion(enum_node), |
| | 28890 | .tagged_union_two, |
| | 28891 | .tagged_union_two_trailing, |
| | 28892 | => tree.taggedUnionTwo(&buffer, enum_node), |
| | 28893 | .tagged_union_enum_tag, |
| | 28894 | .tagged_union_enum_tag_trailing, |
| | 28895 | => tree.taggedUnionEnumTag(enum_node), |
| | 28896 | |
| 28736 | // Container was constructed with `@Type`. | 28897 | // Container was constructed with `@Type`. |
| 28737 | else => return LazySrcLoc.nodeOffset(0), | 28898 | else => return LazySrcLoc.nodeOffset(0), |
| 28738 | }; | 28899 | }; |
| ... | @@ -29383,7 +29544,9 @@ fn unionFieldAlignment( | ... | @@ -29383,7 +29544,9 @@ fn unionFieldAlignment( |
| 29383 | src: LazySrcLoc, | 29544 | src: LazySrcLoc, |
| 29384 | field: Module.Union.Field, | 29545 | field: Module.Union.Field, |
| 29385 | ) !u32 { | 29546 | ) !u32 { |
| 29386 | if (field.abi_align == 0) { | 29547 | if (field.ty.zigTypeTag() == .NoReturn) { |
| | 29548 | return @as(u32, 0); |
| | 29549 | } else if (field.abi_align == 0) { |
| 29387 | return sema.typeAbiAlignment(block, src, field.ty); | 29550 | return sema.typeAbiAlignment(block, src, field.ty); |
| 29388 | } else { | 29551 | } else { |
| 29389 | return field.abi_align; | 29552 | return field.abi_align; |