| ... | ... | @@ -2497,18 +2497,6 @@ fn zirEnumDecl( |
| 2497 | 2497 | extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl); |
| 2498 | 2498 | |
| 2499 | 2499 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 2500 | | if (fields_len == 0) { |
| 2501 | | assert(body.len == 0); |
| 2502 | | if (tag_type_ref != .none) { |
| 2503 | | const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); |
| 2504 | | if (ty.zigTypeTag() != .Int and ty.zigTypeTag() != .ComptimeInt) { |
| 2505 | | return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); |
| 2506 | | } |
| 2507 | | enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator); |
| 2508 | | enum_obj.tag_ty_inferred = false; |
| 2509 | | } |
| 2510 | | return decl_val; |
| 2511 | | } |
| 2512 | 2500 | extra_index += body.len; |
| 2513 | 2501 | |
| 2514 | 2502 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; |
| ... | ... | @@ -2566,6 +2554,9 @@ fn zirEnumDecl( |
| 2566 | 2554 | } |
| 2567 | 2555 | enum_obj.tag_ty = try ty.copy(decl_arena_allocator); |
| 2568 | 2556 | enum_obj.tag_ty_inferred = false; |
| 2557 | } else if (fields_len == 0) { |
| 2558 | enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, 0); |
| 2559 | enum_obj.tag_ty_inferred = true; |
| 2569 | 2560 | } else { |
| 2570 | 2561 | const bits = std.math.log2_int_ceil(usize, fields_len); |
| 2571 | 2562 | enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, bits); |
| ... | ... | @@ -3788,6 +3779,7 @@ fn validateStructInit( |
| 3788 | 3779 | if ((is_comptime or block.is_comptime) and |
| 3789 | 3780 | (try sema.resolveDefinedValue(block, init_src, struct_ptr)) != null) |
| 3790 | 3781 | { |
| 3782 | try sema.resolveStructLayout(block, init_src, struct_ty); |
| 3791 | 3783 | // In this case the only thing we need to do is evaluate the implicit |
| 3792 | 3784 | // store instructions for default field values, and report any missing fields. |
| 3793 | 3785 | // Avoid the cost of the extra machinery for detecting a comptime struct init value. |
| ... | ... | @@ -3982,6 +3974,7 @@ fn validateStructInit( |
| 3982 | 3974 | try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store); |
| 3983 | 3975 | return; |
| 3984 | 3976 | } |
| 3977 | try sema.resolveStructLayout(block, init_src, struct_ty); |
| 3985 | 3978 | |
| 3986 | 3979 | // Our task is to insert `store` instructions for all the default field values. |
| 3987 | 3980 | for (found_fields) |field_ptr, i| { |
| ... | ... | @@ -9003,6 +8996,9 @@ fn zirSwitchCond( |
| 9003 | 8996 | .ErrorSet, |
| 9004 | 8997 | .Enum, |
| 9005 | 8998 | => { |
| 8999 | if (operand_ty.isSlice()) { |
| 9000 | return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(sema.mod)}); |
| 9001 | } |
| 9006 | 9002 | if ((try sema.typeHasOnePossibleValue(block, operand_src, operand_ty))) |opv| { |
| 9007 | 9003 | return sema.addConstant(operand_ty, opv); |
| 9008 | 9004 | } |
| ... | ... | @@ -15849,6 +15845,7 @@ fn finishStructInit( |
| 15849 | 15845 | } |
| 15850 | 15846 | |
| 15851 | 15847 | if (is_ref) { |
| 15848 | try sema.resolveStructLayout(block, dest_src, struct_ty); |
| 15852 | 15849 | const target = sema.mod.getTarget(); |
| 15853 | 15850 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 15854 | 15851 | .pointee_type = struct_ty, |
| ... | ... | @@ -21895,17 +21892,18 @@ fn unionFieldPtr( |
| 21895 | 21892 | if (union_val.isUndef()) { |
| 21896 | 21893 | return sema.failWithUseOfUndef(block, src); |
| 21897 | 21894 | } |
| 21895 | const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?; |
| 21898 | 21896 | const tag_and_val = union_val.castTag(.@"union").?.data; |
| 21899 | 21897 | var field_tag_buf: Value.Payload.U32 = .{ |
| 21900 | 21898 | .base = .{ .tag = .enum_field_index }, |
| 21901 | | .data = field_index, |
| 21899 | .data = @intCast(u32, enum_field_index), |
| 21902 | 21900 | }; |
| 21903 | 21901 | const field_tag = Value.initPayload(&field_tag_buf.base); |
| 21904 | 21902 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); |
| 21905 | 21903 | if (!tag_matches) { |
| 21906 | 21904 | const msg = msg: { |
| 21907 | 21905 | const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data; |
| 21908 | | const active_field_name = union_obj.fields.keys()[active_index]; |
| 21906 | const active_field_name = union_obj.tag_ty.enumFieldName(active_index); |
| 21909 | 21907 | const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name }); |
| 21910 | 21908 | errdefer msg.destroy(sema.gpa); |
| 21911 | 21909 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | ... | @@ -21930,12 +21928,11 @@ fn unionFieldPtr( |
| 21930 | 21928 | if (!initializing and union_obj.layout == .Auto and block.wantSafety() and |
| 21931 | 21929 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) |
| 21932 | 21930 | { |
| 21933 | | const enum_ty = union_ty.unionTagTypeHypothetical(); |
| 21934 | 21931 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); |
| 21935 | | const wanted_tag = try sema.addConstant(enum_ty, wanted_tag_val); |
| 21932 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); |
| 21936 | 21933 | // TODO would it be better if get_union_tag supported pointers to unions? |
| 21937 | 21934 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); |
| 21938 | | const active_tag = try block.addTyOp(.get_union_tag, enum_ty, union_val); |
| 21935 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val); |
| 21939 | 21936 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 21940 | 21937 | try sema.addSafetyCheck(block, ok, .inactive_union_field); |
| 21941 | 21938 | } |
| ... | ... | @@ -21966,9 +21963,10 @@ fn unionFieldVal( |
| 21966 | 21963 | if (union_val.isUndef()) return sema.addConstUndef(field.ty); |
| 21967 | 21964 | |
| 21968 | 21965 | const tag_and_val = union_val.castTag(.@"union").?.data; |
| 21966 | const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?; |
| 21969 | 21967 | var field_tag_buf: Value.Payload.U32 = .{ |
| 21970 | 21968 | .base = .{ .tag = .enum_field_index }, |
| 21971 | | .data = field_index, |
| 21969 | .data = @intCast(u32, enum_field_index), |
| 21972 | 21970 | }; |
| 21973 | 21971 | const field_tag = Value.initPayload(&field_tag_buf.base); |
| 21974 | 21972 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); |
| ... | ... | @@ -21979,7 +21977,7 @@ fn unionFieldVal( |
| 21979 | 21977 | } else { |
| 21980 | 21978 | const msg = msg: { |
| 21981 | 21979 | const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data; |
| 21982 | | const active_field_name = union_obj.fields.keys()[active_index]; |
| 21980 | const active_field_name = union_obj.tag_ty.enumFieldName(active_index); |
| 21983 | 21981 | const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name }); |
| 21984 | 21982 | errdefer msg.destroy(sema.gpa); |
| 21985 | 21983 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | ... | @@ -22004,10 +22002,9 @@ fn unionFieldVal( |
| 22004 | 22002 | if (union_obj.layout == .Auto and block.wantSafety() and |
| 22005 | 22003 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) |
| 22006 | 22004 | { |
| 22007 | | const enum_ty = union_ty.unionTagTypeHypothetical(); |
| 22008 | 22005 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); |
| 22009 | | const wanted_tag = try sema.addConstant(enum_ty, wanted_tag_val); |
| 22010 | | const active_tag = try block.addTyOp(.get_union_tag, enum_ty, union_byval); |
| 22006 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); |
| 22007 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval); |
| 22011 | 22008 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 22012 | 22009 | try sema.addSafetyCheck(block, ok, .inactive_union_field); |
| 22013 | 22010 | } |
| ... | ... | @@ -22254,8 +22251,7 @@ fn tupleField( |
| 22254 | 22251 | |
| 22255 | 22252 | if (try sema.resolveMaybeUndefVal(block, tuple_src, tuple)) |tuple_val| { |
| 22256 | 22253 | if (tuple_val.isUndef()) return sema.addConstUndef(field_ty); |
| 22257 | | const field_values = tuple_val.castTag(.aggregate).?.data; |
| 22258 | | return sema.addConstant(field_ty, field_values[field_index]); |
| 22254 | return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, field_index)); |
| 22259 | 22255 | } |
| 22260 | 22256 | |
| 22261 | 22257 | try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src); |
| ... | ... | @@ -28854,10 +28850,11 @@ pub fn typeHasOnePossibleValue( |
| 28854 | 28850 | |
| 28855 | 28851 | .tuple, .anon_struct => { |
| 28856 | 28852 | const tuple = ty.tupleFields(); |
| 28857 | | for (tuple.values) |val| { |
| 28858 | | if (val.tag() == .unreachable_value) { |
| 28859 | | return null; // non-comptime field |
| 28860 | | } |
| 28853 | for (tuple.values) |val, i| { |
| 28854 | const is_comptime = val.tag() != .unreachable_value; |
| 28855 | if (is_comptime) continue; |
| 28856 | if ((try sema.typeHasOnePossibleValue(block, src, tuple.types[i])) != null) continue; |
| 28857 | return null; |
| 28861 | 28858 | } |
| 28862 | 28859 | return Value.initTag(.empty_struct_value); |
| 28863 | 28860 | }, |