authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-07 21:48:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:42:30-07:00
log3116477dcc5e85d8fe7b2be2f332796e1425f956
tree942527f29fb76af961c6a73986a05639d14c1c97
parent2f9b7dc1023e9ff21574b559e22265db65e00d2d

stage2: move empty struct type and value to InternPool


5 files changed, 2079 insertions(+), 2038 deletions(-)

src/Sema.zig+521-514
......@@ -12615,7 +12615,7 @@ fn analyzeTupleCat(
1261512615 const dest_fields = lhs_len + rhs_len;
1261612616
1261712617 if (dest_fields == 0) {
12618 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
12618 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);
1261912619 }
1262012620 if (lhs_len == 0) {
1262112621 return rhs;
......@@ -12943,7 +12943,7 @@ fn analyzeTupleMul(
1294312943 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1294412944
1294512945 if (final_len_u64 == 0) {
12946 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
12946 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);
1294712947 }
1294812948 const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);
1294912949
......@@ -21860,7 +21860,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2186021860 const args = try sema.resolveInst(extra.args);
2186121861
2186221862 const args_ty = sema.typeOf(args);
21863 if (!args_ty.isTuple() and args_ty.tag() != .empty_struct_literal) {
21863 if (!args_ty.isTuple() and args_ty.ip_index != .empty_struct_type) {
2186421864 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});
2186521865 }
2186621866
......@@ -24780,37 +24780,41 @@ fn structFieldVal(
2478024780 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
2478124781
2478224782 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24783 switch (struct_ty.tag()) {
24784 .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24785 .anon_struct => {
24786 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24787 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24788 },
24789 .@"struct" => {
24790 const struct_obj = struct_ty.castTag(.@"struct").?.data;
24791 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
24792
24793 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24794 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
24795 const field_index = @intCast(u32, field_index_usize);
24796 const field = struct_obj.fields.values()[field_index];
24783 switch (struct_ty.ip_index) {
24784 .empty_struct_type => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24785 .none => switch (struct_ty.tag()) {
24786 .tuple => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24787 .anon_struct => {
24788 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24789 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24790 },
24791 .@"struct" => {
24792 const struct_obj = struct_ty.castTag(.@"struct").?.data;
24793 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2479724794
24798 if (field.is_comptime) {
24799 return sema.addConstant(field.ty, field.default_val);
24800 }
24795 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24796 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
24797 const field_index = @intCast(u32, field_index_usize);
24798 const field = struct_obj.fields.values()[field_index];
2480124799
24802 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {
24803 if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
24804 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24805 return sema.addConstant(field.ty, opv);
24800 if (field.is_comptime) {
24801 return sema.addConstant(field.ty, field.default_val);
2480624802 }
2480724803
24808 const field_values = struct_val.castTag(.aggregate).?.data;
24809 return sema.addConstant(field.ty, field_values[field_index]);
24810 }
24804 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {
24805 if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
24806 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24807 return sema.addConstant(field.ty, opv);
24808 }
24809
24810 const field_values = struct_val.castTag(.aggregate).?.data;
24811 return sema.addConstant(field.ty, field_values[field_index]);
24812 }
2481124813
24812 try sema.requireRuntimeBlock(block, src, null);
24813 return block.addStructFieldVal(struct_byval, field_index, field.ty);
24814 try sema.requireRuntimeBlock(block, src, null);
24815 return block.addStructFieldVal(struct_byval, field_index, field.ty);
24816 },
24817 else => unreachable,
2481424818 },
2481524819 else => unreachable,
2481624820 }
......@@ -27848,6 +27852,19 @@ fn beginComptimePtrMutation(
2784827852 else => unreachable,
2784927853 }
2785027854 },
27855 .empty_struct => {
27856 const duped = try sema.arena.create(Value);
27857 duped.* = Value.initTag(.the_only_possible_value);
27858 return beginComptimePtrMutationInner(
27859 sema,
27860 block,
27861 src,
27862 parent.ty.structFieldType(field_index),
27863 duped,
27864 ptr_elem_ty,
27865 parent.decl_ref_mut,
27866 );
27867 },
2785127868 .none => switch (val_ptr.tag()) {
2785227869 .aggregate => return beginComptimePtrMutationInner(
2785327870 sema,
......@@ -27901,20 +27918,6 @@ fn beginComptimePtrMutation(
2790127918 else => unreachable,
2790227919 },
2790327920
27904 .empty_struct_value => {
27905 const duped = try sema.arena.create(Value);
27906 duped.* = Value.initTag(.the_only_possible_value);
27907 return beginComptimePtrMutationInner(
27908 sema,
27909 block,
27910 src,
27911 parent.ty.structFieldType(field_index),
27912 duped,
27913 ptr_elem_ty,
27914 parent.decl_ref_mut,
27915 );
27916 },
27917
2791827921 else => unreachable,
2791927922 },
2792027923 else => unreachable,
......@@ -31502,174 +31505,174 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3150231505pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3150331506 const mod = sema.mod;
3150431507
31505 if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31506 .int_type => false,
31507 .ptr_type => |ptr_type| {
31508 const child_ty = ptr_type.elem_type.toType();
31509 if (child_ty.zigTypeTag(mod) == .Fn) {
31510 return child_ty.fnInfo().is_generic;
31511 } else {
31512 return sema.resolveTypeRequiresComptime(child_ty);
31513 }
31514 },
31515 .array_type => |array_type| return sema.resolveTypeRequiresComptime(array_type.child.toType()),
31516 .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),
31517 .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),
31518 .error_union_type => |error_union_type| return sema.resolveTypeRequiresComptime(error_union_type.payload_type.toType()),
31519 .simple_type => |t| switch (t) {
31520 .f16,
31521 .f32,
31522 .f64,
31523 .f80,
31524 .f128,
31525 .usize,
31526 .isize,
31527 .c_char,
31528 .c_short,
31529 .c_ushort,
31530 .c_int,
31531 .c_uint,
31532 .c_long,
31533 .c_ulong,
31534 .c_longlong,
31535 .c_ulonglong,
31536 .c_longdouble,
31537 .anyopaque,
31538 .bool,
31539 .void,
31540 .anyerror,
31541 .@"anyframe",
31542 .noreturn,
31543 .generic_poison,
31544 .atomic_order,
31545 .atomic_rmw_op,
31546 .calling_convention,
31547 .address_space,
31548 .float_mode,
31549 .reduce_op,
31550 .call_modifier,
31551 .prefetch_options,
31552 .export_options,
31553 .extern_options,
31508 return switch (ty.ip_index) {
31509 .empty_struct_type => false,
31510 .none => switch (ty.tag()) {
31511 .empty_struct,
31512 .error_set,
31513 .error_set_single,
31514 .error_set_inferred,
31515 .error_set_merged,
31516 .@"opaque",
31517 .enum_simple,
3155431518 => false,
3155531519
31556 .type,
31557 .comptime_int,
31558 .comptime_float,
31559 .null,
31560 .undefined,
31561 .enum_literal,
31562 .type_info,
31563 => true,
31564
31565 .var_args_param => unreachable,
31566 },
31567 .struct_type => @panic("TODO"),
31568 .union_type => @panic("TODO"),
31569 .simple_value => unreachable,
31570 .extern_func => unreachable,
31571 .int => unreachable,
31572 .enum_tag => unreachable, // it's a value, not a type
31573 };
31574
31575 return switch (ty.tag()) {
31576 .empty_struct_literal,
31577 .empty_struct,
31578 .error_set,
31579 .error_set_single,
31580 .error_set_inferred,
31581 .error_set_merged,
31582 .@"opaque",
31583 .enum_simple,
31584 => false,
31520 .function => true,
3158531521
31586 .function => true,
31522 .inferred_alloc_mut => unreachable,
31523 .inferred_alloc_const => unreachable,
3158731524
31588 .inferred_alloc_mut => unreachable,
31589 .inferred_alloc_const => unreachable,
31525 .array,
31526 .array_sentinel,
31527 => return sema.resolveTypeRequiresComptime(ty.childType(mod)),
3159031528
31591 .array,
31592 .array_sentinel,
31593 => return sema.resolveTypeRequiresComptime(ty.childType(mod)),
31529 .pointer => {
31530 const child_ty = ty.childType(mod);
31531 if (child_ty.zigTypeTag(mod) == .Fn) {
31532 return child_ty.fnInfo().is_generic;
31533 } else {
31534 return sema.resolveTypeRequiresComptime(child_ty);
31535 }
31536 },
3159431537
31595 .pointer => {
31596 const child_ty = ty.childType(mod);
31597 if (child_ty.zigTypeTag(mod) == .Fn) {
31598 return child_ty.fnInfo().is_generic;
31599 } else {
31600 return sema.resolveTypeRequiresComptime(child_ty);
31601 }
31602 },
31538 .optional => {
31539 return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));
31540 },
3160331541
31604 .optional => {
31605 return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));
31606 },
31542 .tuple, .anon_struct => {
31543 const tuple = ty.tupleFields();
31544 for (tuple.types, 0..) |field_ty, i| {
31545 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
31546 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {
31547 return true;
31548 }
31549 }
31550 return false;
31551 },
3160731552
31608 .tuple, .anon_struct => {
31609 const tuple = ty.tupleFields();
31610 for (tuple.types, 0..) |field_ty, i| {
31611 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
31612 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {
31613 return true;
31553 .@"struct" => {
31554 const struct_obj = ty.castTag(.@"struct").?.data;
31555 switch (struct_obj.requires_comptime) {
31556 .no, .wip => return false,
31557 .yes => return true,
31558 .unknown => {
31559 var requires_comptime = false;
31560 struct_obj.requires_comptime = .wip;
31561 for (struct_obj.fields.values()) |field| {
31562 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31563 }
31564 if (requires_comptime) {
31565 struct_obj.requires_comptime = .yes;
31566 } else {
31567 struct_obj.requires_comptime = .no;
31568 }
31569 return requires_comptime;
31570 },
3161431571 }
31615 }
31616 return false;
31617 },
31572 },
3161831573
31619 .@"struct" => {
31620 const struct_obj = ty.castTag(.@"struct").?.data;
31621 switch (struct_obj.requires_comptime) {
31622 .no, .wip => return false,
31623 .yes => return true,
31624 .unknown => {
31625 var requires_comptime = false;
31626 struct_obj.requires_comptime = .wip;
31627 for (struct_obj.fields.values()) |field| {
31628 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31629 }
31630 if (requires_comptime) {
31631 struct_obj.requires_comptime = .yes;
31632 } else {
31633 struct_obj.requires_comptime = .no;
31634 }
31635 return requires_comptime;
31636 },
31637 }
31638 },
31574 .@"union", .union_safety_tagged, .union_tagged => {
31575 const union_obj = ty.cast(Type.Payload.Union).?.data;
31576 switch (union_obj.requires_comptime) {
31577 .no, .wip => return false,
31578 .yes => return true,
31579 .unknown => {
31580 var requires_comptime = false;
31581 union_obj.requires_comptime = .wip;
31582 for (union_obj.fields.values()) |field| {
31583 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31584 }
31585 if (requires_comptime) {
31586 union_obj.requires_comptime = .yes;
31587 } else {
31588 union_obj.requires_comptime = .no;
31589 }
31590 return requires_comptime;
31591 },
31592 }
31593 },
3163931594
31640 .@"union", .union_safety_tagged, .union_tagged => {
31641 const union_obj = ty.cast(Type.Payload.Union).?.data;
31642 switch (union_obj.requires_comptime) {
31643 .no, .wip => return false,
31644 .yes => return true,
31645 .unknown => {
31646 var requires_comptime = false;
31647 union_obj.requires_comptime = .wip;
31648 for (union_obj.fields.values()) |field| {
31649 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31650 }
31651 if (requires_comptime) {
31652 union_obj.requires_comptime = .yes;
31653 } else {
31654 union_obj.requires_comptime = .no;
31655 }
31656 return requires_comptime;
31657 },
31658 }
31595 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
31596 .anyframe_T => {
31597 const child_ty = ty.castTag(.anyframe_T).?.data;
31598 return sema.resolveTypeRequiresComptime(child_ty);
31599 },
31600 .enum_numbered => {
31601 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
31602 return sema.resolveTypeRequiresComptime(tag_ty);
31603 },
31604 .enum_full, .enum_nonexhaustive => {
31605 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
31606 return sema.resolveTypeRequiresComptime(tag_ty);
31607 },
3165931608 },
31609 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
31610 .int_type => false,
31611 .ptr_type => |ptr_type| {
31612 const child_ty = ptr_type.elem_type.toType();
31613 if (child_ty.zigTypeTag(mod) == .Fn) {
31614 return child_ty.fnInfo().is_generic;
31615 } else {
31616 return sema.resolveTypeRequiresComptime(child_ty);
31617 }
31618 },
31619 .array_type => |array_type| return sema.resolveTypeRequiresComptime(array_type.child.toType()),
31620 .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),
31621 .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),
31622 .error_union_type => |error_union_type| return sema.resolveTypeRequiresComptime(error_union_type.payload_type.toType()),
31623 .simple_type => |t| switch (t) {
31624 .f16,
31625 .f32,
31626 .f64,
31627 .f80,
31628 .f128,
31629 .usize,
31630 .isize,
31631 .c_char,
31632 .c_short,
31633 .c_ushort,
31634 .c_int,
31635 .c_uint,
31636 .c_long,
31637 .c_ulong,
31638 .c_longlong,
31639 .c_ulonglong,
31640 .c_longdouble,
31641 .anyopaque,
31642 .bool,
31643 .void,
31644 .anyerror,
31645 .@"anyframe",
31646 .noreturn,
31647 .generic_poison,
31648 .var_args_param,
31649 .atomic_order,
31650 .atomic_rmw_op,
31651 .calling_convention,
31652 .address_space,
31653 .float_mode,
31654 .reduce_op,
31655 .call_modifier,
31656 .prefetch_options,
31657 .export_options,
31658 .extern_options,
31659 => false,
3166031660
31661 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
31662 .anyframe_T => {
31663 const child_ty = ty.castTag(.anyframe_T).?.data;
31664 return sema.resolveTypeRequiresComptime(child_ty);
31665 },
31666 .enum_numbered => {
31667 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
31668 return sema.resolveTypeRequiresComptime(tag_ty);
31669 },
31670 .enum_full, .enum_nonexhaustive => {
31671 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
31672 return sema.resolveTypeRequiresComptime(tag_ty);
31661 .type,
31662 .comptime_int,
31663 .comptime_float,
31664 .null,
31665 .undefined,
31666 .enum_literal,
31667 .type_info,
31668 => true,
31669 },
31670 .struct_type => @panic("TODO"),
31671 .union_type => @panic("TODO"),
31672 .simple_value => unreachable,
31673 .extern_func => unreachable,
31674 .int => unreachable,
31675 .enum_tag => unreachable, // it's a value, not a type
3167331676 },
3167431677 };
3167531678}
......@@ -32957,237 +32960,240 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
3295732960pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3295832961 const mod = sema.mod;
3295932962
32960 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
32961 .int_type => |int_type| {
32962 if (int_type.bits == 0) {
32963 return try mod.intValue(ty, 0);
32964 } else {
32965 return null;
32966 }
32967 },
32968 .ptr_type => return null,
32969 .array_type => |array_type| {
32970 if (array_type.len == 0)
32971 return Value.initTag(.empty_array);
32972 if ((try sema.typeHasOnePossibleValue(array_type.child.toType())) != null) {
32973 return Value.initTag(.the_only_possible_value);
32974 }
32975 return null;
32976 },
32977 .vector_type => |vector_type| {
32978 if (vector_type.len == 0) return Value.initTag(.empty_array);
32979 if (try sema.typeHasOnePossibleValue(vector_type.child.toType())) |v| return v;
32980 return null;
32981 },
32982 .opt_type => |child| {
32983 if (child.toType().isNoReturn()) {
32984 return Value.null;
32985 } else {
32986 return null;
32987 }
32988 },
32989 .error_union_type => return null,
32990 .simple_type => |t| switch (t) {
32991 .f16,
32992 .f32,
32993 .f64,
32994 .f80,
32995 .f128,
32996 .usize,
32997 .isize,
32998 .c_char,
32999 .c_short,
33000 .c_ushort,
33001 .c_int,
33002 .c_uint,
33003 .c_long,
33004 .c_ulong,
33005 .c_longlong,
33006 .c_ulonglong,
33007 .c_longdouble,
33008 .anyopaque,
33009 .bool,
33010 .type,
33011 .anyerror,
33012 .comptime_int,
33013 .comptime_float,
33014 .@"anyframe",
33015 .enum_literal,
33016 .atomic_order,
33017 .atomic_rmw_op,
33018 .calling_convention,
33019 .address_space,
33020 .float_mode,
33021 .reduce_op,
33022 .call_modifier,
33023 .prefetch_options,
33024 .export_options,
33025 .extern_options,
33026 .type_info,
33027 => return null,
32963 switch (ty.ip_index) {
32964 .empty_struct_type => return Value.empty_struct,
3302832965
33029 .void => return Value.void,
33030 .noreturn => return Value.@"unreachable",
33031 .null => return Value.null,
33032 .undefined => return Value.undef,
32966 .none => switch (ty.tag()) {
32967 .error_set_single,
32968 .error_set,
32969 .error_set_merged,
32970 .error_union,
32971 .function,
32972 .array_sentinel,
32973 .error_set_inferred,
32974 .@"opaque",
32975 .anyframe_T,
32976 .pointer,
32977 => return null,
3303332978
33034 .generic_poison => return error.GenericPoison,
33035 .var_args_param => unreachable,
33036 },
33037 .struct_type => @panic("TODO"),
33038 .union_type => @panic("TODO"),
33039 .simple_value => unreachable,
33040 .extern_func => unreachable,
33041 .int => unreachable,
33042 .enum_tag => unreachable, // it's a value, not a type
33043 };
32979 .optional => {
32980 const child_ty = ty.optionalChild(mod);
32981 if (child_ty.isNoReturn()) {
32982 return Value.null;
32983 } else {
32984 return null;
32985 }
32986 },
3304432987
33045 switch (ty.tag()) {
33046 .error_set_single,
33047 .error_set,
33048 .error_set_merged,
33049 .error_union,
33050 .function,
33051 .array_sentinel,
33052 .error_set_inferred,
33053 .@"opaque",
33054 .anyframe_T,
33055 .pointer,
33056 => return null,
32988 .@"struct" => {
32989 const resolved_ty = try sema.resolveTypeFields(ty);
32990 const s = resolved_ty.castTag(.@"struct").?.data;
32991 for (s.fields.values(), 0..) |field, i| {
32992 if (field.is_comptime) continue;
32993 if (field.ty.eql(resolved_ty, sema.mod)) {
32994 const msg = try Module.ErrorMsg.create(
32995 sema.gpa,
32996 s.srcLoc(sema.mod),
32997 "struct '{}' depends on itself",
32998 .{ty.fmt(sema.mod)},
32999 );
33000 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
33001 return sema.failWithOwnedErrorMsg(msg);
33002 }
33003 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {
33004 return null;
33005 }
33006 }
33007 return Value.empty_struct;
33008 },
3305733009
33058 .optional => {
33059 const child_ty = ty.optionalChild(mod);
33060 if (child_ty.isNoReturn()) {
33061 return Value.null;
33062 } else {
33063 return null;
33064 }
33065 },
33010 .tuple, .anon_struct => {
33011 const tuple = ty.tupleFields();
33012 for (tuple.values, 0..) |val, i| {
33013 const is_comptime = val.ip_index != .unreachable_value;
33014 if (is_comptime) continue;
33015 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;
33016 return null;
33017 }
33018 return Value.empty_struct;
33019 },
3306633020
33067 .@"struct" => {
33068 const resolved_ty = try sema.resolveTypeFields(ty);
33069 const s = resolved_ty.castTag(.@"struct").?.data;
33070 for (s.fields.values(), 0..) |field, i| {
33071 if (field.is_comptime) continue;
33072 if (field.ty.eql(resolved_ty, sema.mod)) {
33021 .enum_numbered => {
33022 const resolved_ty = try sema.resolveTypeFields(ty);
33023 const enum_obj = resolved_ty.castTag(.enum_numbered).?.data;
33024 // An explicit tag type is always provided for enum_numbered.
33025 if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) {
33026 return null;
33027 }
33028 if (enum_obj.fields.count() == 1) {
33029 if (enum_obj.values.count() == 0) {
33030 return try mod.intValue(ty, 0); // auto-numbered
33031 } else {
33032 return enum_obj.values.keys()[0];
33033 }
33034 } else {
33035 return null;
33036 }
33037 },
33038 .enum_full => {
33039 const resolved_ty = try sema.resolveTypeFields(ty);
33040 const enum_obj = resolved_ty.castTag(.enum_full).?.data;
33041 if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) {
33042 return null;
33043 }
33044 switch (enum_obj.fields.count()) {
33045 0 => return Value.@"unreachable",
33046 1 => if (enum_obj.values.count() == 0) {
33047 return try mod.intValue(ty, 0); // auto-numbered
33048 } else {
33049 return enum_obj.values.keys()[0];
33050 },
33051 else => return null,
33052 }
33053 },
33054 .enum_simple => {
33055 const resolved_ty = try sema.resolveTypeFields(ty);
33056 const enum_simple = resolved_ty.castTag(.enum_simple).?.data;
33057 switch (enum_simple.fields.count()) {
33058 0 => return Value.@"unreachable",
33059 1 => return try mod.intValue(ty, 0),
33060 else => return null,
33061 }
33062 },
33063 .enum_nonexhaustive => {
33064 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
33065 if (tag_ty.zigTypeTag(mod) != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) {
33066 return try mod.intValue(ty, 0);
33067 } else {
33068 return null;
33069 }
33070 },
33071 .@"union", .union_safety_tagged, .union_tagged => {
33072 const resolved_ty = try sema.resolveTypeFields(ty);
33073 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
33074 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse
33075 return null;
33076 const fields = union_obj.fields.values();
33077 if (fields.len == 0) return Value.@"unreachable";
33078 const only_field = fields[0];
33079 if (only_field.ty.eql(resolved_ty, sema.mod)) {
3307333080 const msg = try Module.ErrorMsg.create(
3307433081 sema.gpa,
33075 s.srcLoc(sema.mod),
33076 "struct '{}' depends on itself",
33082 union_obj.srcLoc(sema.mod),
33083 "union '{}' depends on itself",
3307733084 .{ty.fmt(sema.mod)},
3307833085 );
33079 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
33086 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
3308033087 return sema.failWithOwnedErrorMsg(msg);
3308133088 }
33082 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {
33089 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
3308333090 return null;
33084 }
33085 }
33086 return Value.initTag(.empty_struct_value);
33087 },
33091 // TODO make this not allocate.
33092 return try Value.Tag.@"union".create(sema.arena, .{
33093 .tag = tag_val,
33094 .val = val_val,
33095 });
33096 },
33097
33098 .empty_struct => return Value.empty_struct,
3308833099
33089 .tuple, .anon_struct => {
33090 const tuple = ty.tupleFields();
33091 for (tuple.values, 0..) |val, i| {
33092 const is_comptime = val.ip_index != .unreachable_value;
33093 if (is_comptime) continue;
33094 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;
33100 .array => {
33101 if (ty.arrayLen(mod) == 0)
33102 return Value.initTag(.empty_array);
33103 if ((try sema.typeHasOnePossibleValue(ty.childType(mod))) != null) {
33104 return Value.initTag(.the_only_possible_value);
33105 }
3309533106 return null;
33096 }
33097 return Value.initTag(.empty_struct_value);
33107 },
33108
33109 .inferred_alloc_const => unreachable,
33110 .inferred_alloc_mut => unreachable,
3309833111 },
3309933112
33100 .enum_numbered => {
33101 const resolved_ty = try sema.resolveTypeFields(ty);
33102 const enum_obj = resolved_ty.castTag(.enum_numbered).?.data;
33103 // An explicit tag type is always provided for enum_numbered.
33104 if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) {
33105 return null;
33106 }
33107 if (enum_obj.fields.count() == 1) {
33108 if (enum_obj.values.count() == 0) {
33109 return try mod.intValue(ty, 0); // auto-numbered
33113 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
33114 .int_type => |int_type| {
33115 if (int_type.bits == 0) {
33116 return try mod.intValue(ty, 0);
3311033117 } else {
33111 return enum_obj.values.keys()[0];
33118 return null;
33119 }
33120 },
33121 .ptr_type => return null,
33122 .array_type => |array_type| {
33123 if (array_type.len == 0)
33124 return Value.initTag(.empty_array);
33125 if ((try sema.typeHasOnePossibleValue(array_type.child.toType())) != null) {
33126 return Value.initTag(.the_only_possible_value);
3311233127 }
33113 } else {
3311433128 return null;
33115 }
33116 },
33117 .enum_full => {
33118 const resolved_ty = try sema.resolveTypeFields(ty);
33119 const enum_obj = resolved_ty.castTag(.enum_full).?.data;
33120 if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) {
33129 },
33130 .vector_type => |vector_type| {
33131 if (vector_type.len == 0) return Value.initTag(.empty_array);
33132 if (try sema.typeHasOnePossibleValue(vector_type.child.toType())) |v| return v;
3312133133 return null;
33122 }
33123 switch (enum_obj.fields.count()) {
33124 0 => return Value.@"unreachable",
33125 1 => if (enum_obj.values.count() == 0) {
33126 return try mod.intValue(ty, 0); // auto-numbered
33134 },
33135 .opt_type => |child| {
33136 if (child.toType().isNoReturn()) {
33137 return Value.null;
3312733138 } else {
33128 return enum_obj.values.keys()[0];
33129 },
33130 else => return null,
33131 }
33132 },
33133 .enum_simple => {
33134 const resolved_ty = try sema.resolveTypeFields(ty);
33135 const enum_simple = resolved_ty.castTag(.enum_simple).?.data;
33136 switch (enum_simple.fields.count()) {
33137 0 => return Value.@"unreachable",
33138 1 => return try mod.intValue(ty, 0),
33139 else => return null,
33140 }
33141 },
33142 .enum_nonexhaustive => {
33143 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
33144 if (tag_ty.zigTypeTag(mod) != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) {
33145 return try mod.intValue(ty, 0);
33146 } else {
33147 return null;
33148 }
33149 },
33150 .@"union", .union_safety_tagged, .union_tagged => {
33151 const resolved_ty = try sema.resolveTypeFields(ty);
33152 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
33153 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse
33154 return null;
33155 const fields = union_obj.fields.values();
33156 if (fields.len == 0) return Value.@"unreachable";
33157 const only_field = fields[0];
33158 if (only_field.ty.eql(resolved_ty, sema.mod)) {
33159 const msg = try Module.ErrorMsg.create(
33160 sema.gpa,
33161 union_obj.srcLoc(sema.mod),
33162 "union '{}' depends on itself",
33163 .{ty.fmt(sema.mod)},
33164 );
33165 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
33166 return sema.failWithOwnedErrorMsg(msg);
33167 }
33168 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
33169 return null;
33170 // TODO make this not allocate. The function in `Type.onePossibleValue`
33171 // currently returns `empty_struct_value` and we should do that here too.
33172 return try Value.Tag.@"union".create(sema.arena, .{
33173 .tag = tag_val,
33174 .val = val_val,
33175 });
33176 },
33139 return null;
33140 }
33141 },
33142 .error_union_type => return null,
33143 .simple_type => |t| switch (t) {
33144 .f16,
33145 .f32,
33146 .f64,
33147 .f80,
33148 .f128,
33149 .usize,
33150 .isize,
33151 .c_char,
33152 .c_short,
33153 .c_ushort,
33154 .c_int,
33155 .c_uint,
33156 .c_long,
33157 .c_ulong,
33158 .c_longlong,
33159 .c_ulonglong,
33160 .c_longdouble,
33161 .anyopaque,
33162 .bool,
33163 .type,
33164 .anyerror,
33165 .comptime_int,
33166 .comptime_float,
33167 .@"anyframe",
33168 .enum_literal,
33169 .atomic_order,
33170 .atomic_rmw_op,
33171 .calling_convention,
33172 .address_space,
33173 .float_mode,
33174 .reduce_op,
33175 .call_modifier,
33176 .prefetch_options,
33177 .export_options,
33178 .extern_options,
33179 .type_info,
33180 => return null,
3317733181
33178 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
33182 .void => return Value.void,
33183 .noreturn => return Value.@"unreachable",
33184 .null => return Value.null,
33185 .undefined => return Value.undef,
3317933186
33180 .array => {
33181 if (ty.arrayLen(mod) == 0)
33182 return Value.initTag(.empty_array);
33183 if ((try sema.typeHasOnePossibleValue(ty.childType(mod))) != null) {
33184 return Value.initTag(.the_only_possible_value);
33185 }
33186 return null;
33187 .generic_poison => return error.GenericPoison,
33188 .var_args_param => unreachable,
33189 },
33190 .struct_type => @panic("TODO"),
33191 .union_type => @panic("TODO"),
33192 .simple_value => unreachable,
33193 .extern_func => unreachable,
33194 .int => unreachable,
33195 .enum_tag => unreachable, // it's a value, not a type
3318733196 },
33188
33189 .inferred_alloc_const => unreachable,
33190 .inferred_alloc_mut => unreachable,
3319133197 }
3319233198}
3319333199
......@@ -33567,8 +33573,116 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
3356733573/// elsewhere in value.zig
3356833574pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3356933575 const mod = sema.mod;
33570 if (ty.ip_index != .none) {
33571 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
33576 return switch (ty.ip_index) {
33577 .empty_struct_type => false,
33578
33579 .none => switch (ty.tag()) {
33580 .empty_struct,
33581 .error_set,
33582 .error_set_single,
33583 .error_set_inferred,
33584 .error_set_merged,
33585 .@"opaque",
33586 .enum_simple,
33587 => false,
33588
33589 .function => true,
33590
33591 .inferred_alloc_mut => unreachable,
33592 .inferred_alloc_const => unreachable,
33593
33594 .array,
33595 .array_sentinel,
33596 => return sema.typeRequiresComptime(ty.childType(mod)),
33597
33598 .pointer => {
33599 const child_ty = ty.childType(mod);
33600 if (child_ty.zigTypeTag(mod) == .Fn) {
33601 return child_ty.fnInfo().is_generic;
33602 } else {
33603 return sema.typeRequiresComptime(child_ty);
33604 }
33605 },
33606
33607 .optional => {
33608 return sema.typeRequiresComptime(ty.optionalChild(mod));
33609 },
33610
33611 .tuple, .anon_struct => {
33612 const tuple = ty.tupleFields();
33613 for (tuple.types, 0..) |field_ty, i| {
33614 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
33615 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) {
33616 return true;
33617 }
33618 }
33619 return false;
33620 },
33621
33622 .@"struct" => {
33623 const struct_obj = ty.castTag(.@"struct").?.data;
33624 switch (struct_obj.requires_comptime) {
33625 .no, .wip => return false,
33626 .yes => return true,
33627 .unknown => {
33628 if (struct_obj.status == .field_types_wip)
33629 return false;
33630
33631 try sema.resolveTypeFieldsStruct(ty, struct_obj);
33632
33633 struct_obj.requires_comptime = .wip;
33634 for (struct_obj.fields.values()) |field| {
33635 if (field.is_comptime) continue;
33636 if (try sema.typeRequiresComptime(field.ty)) {
33637 struct_obj.requires_comptime = .yes;
33638 return true;
33639 }
33640 }
33641 struct_obj.requires_comptime = .no;
33642 return false;
33643 },
33644 }
33645 },
33646
33647 .@"union", .union_safety_tagged, .union_tagged => {
33648 const union_obj = ty.cast(Type.Payload.Union).?.data;
33649 switch (union_obj.requires_comptime) {
33650 .no, .wip => return false,
33651 .yes => return true,
33652 .unknown => {
33653 if (union_obj.status == .field_types_wip)
33654 return false;
33655
33656 try sema.resolveTypeFieldsUnion(ty, union_obj);
33657
33658 union_obj.requires_comptime = .wip;
33659 for (union_obj.fields.values()) |field| {
33660 if (try sema.typeRequiresComptime(field.ty)) {
33661 union_obj.requires_comptime = .yes;
33662 return true;
33663 }
33664 }
33665 union_obj.requires_comptime = .no;
33666 return false;
33667 },
33668 }
33669 },
33670
33671 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
33672 .anyframe_T => {
33673 const child_ty = ty.castTag(.anyframe_T).?.data;
33674 return sema.typeRequiresComptime(child_ty);
33675 },
33676 .enum_numbered => {
33677 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
33678 return sema.typeRequiresComptime(tag_ty);
33679 },
33680 .enum_full, .enum_nonexhaustive => {
33681 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
33682 return sema.typeRequiresComptime(tag_ty);
33683 },
33684 },
33685 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3357233686 .int_type => return false,
3357333687 .ptr_type => |ptr_type| {
3357433688 const child_ty = ptr_type.elem_type.toType();
......@@ -33638,113 +33752,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3363833752 .extern_func => unreachable,
3363933753 .int => unreachable,
3364033754 .enum_tag => unreachable, // it's a value, not a type
33641 }
33642 }
33643 return switch (ty.tag()) {
33644 .empty_struct_literal,
33645 .empty_struct,
33646 .error_set,
33647 .error_set_single,
33648 .error_set_inferred,
33649 .error_set_merged,
33650 .@"opaque",
33651 .enum_simple,
33652 => false,
33653
33654 .function => true,
33655
33656 .inferred_alloc_mut => unreachable,
33657 .inferred_alloc_const => unreachable,
33658
33659 .array,
33660 .array_sentinel,
33661 => return sema.typeRequiresComptime(ty.childType(mod)),
33662
33663 .pointer => {
33664 const child_ty = ty.childType(mod);
33665 if (child_ty.zigTypeTag(mod) == .Fn) {
33666 return child_ty.fnInfo().is_generic;
33667 } else {
33668 return sema.typeRequiresComptime(child_ty);
33669 }
33670 },
33671
33672 .optional => {
33673 return sema.typeRequiresComptime(ty.optionalChild(mod));
33674 },
33675
33676 .tuple, .anon_struct => {
33677 const tuple = ty.tupleFields();
33678 for (tuple.types, 0..) |field_ty, i| {
33679 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
33680 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) {
33681 return true;
33682 }
33683 }
33684 return false;
33685 },
33686
33687 .@"struct" => {
33688 const struct_obj = ty.castTag(.@"struct").?.data;
33689 switch (struct_obj.requires_comptime) {
33690 .no, .wip => return false,
33691 .yes => return true,
33692 .unknown => {
33693 if (struct_obj.status == .field_types_wip)
33694 return false;
33695
33696 try sema.resolveTypeFieldsStruct(ty, struct_obj);
33697
33698 struct_obj.requires_comptime = .wip;
33699 for (struct_obj.fields.values()) |field| {
33700 if (field.is_comptime) continue;
33701 if (try sema.typeRequiresComptime(field.ty)) {
33702 struct_obj.requires_comptime = .yes;
33703 return true;
33704 }
33705 }
33706 struct_obj.requires_comptime = .no;
33707 return false;
33708 },
33709 }
33710 },
33711
33712 .@"union", .union_safety_tagged, .union_tagged => {
33713 const union_obj = ty.cast(Type.Payload.Union).?.data;
33714 switch (union_obj.requires_comptime) {
33715 .no, .wip => return false,
33716 .yes => return true,
33717 .unknown => {
33718 if (union_obj.status == .field_types_wip)
33719 return false;
33720
33721 try sema.resolveTypeFieldsUnion(ty, union_obj);
33722
33723 union_obj.requires_comptime = .wip;
33724 for (union_obj.fields.values()) |field| {
33725 if (try sema.typeRequiresComptime(field.ty)) {
33726 union_obj.requires_comptime = .yes;
33727 return true;
33728 }
33729 }
33730 union_obj.requires_comptime = .no;
33731 return false;
33732 },
33733 }
33734 },
33735
33736 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
33737 .anyframe_T => {
33738 const child_ty = ty.castTag(.anyframe_T).?.data;
33739 return sema.typeRequiresComptime(child_ty);
33740 },
33741 .enum_numbered => {
33742 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
33743 return sema.typeRequiresComptime(tag_ty);
33744 },
33745 .enum_full, .enum_nonexhaustive => {
33746 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
33747 return sema.typeRequiresComptime(tag_ty);
3374833755 },
3374933756 };
3375033757}
src/TypedValue.zig+69-60
......@@ -80,67 +80,9 @@ pub fn print(
8080 return writer.writeAll("(variable)");
8181
8282 while (true) switch (val.ip_index) {
83 .empty_struct => return printAggregate(ty, val, writer, level, mod),
8384 .none => switch (val.tag()) {
84 .empty_struct_value, .aggregate => {
85 if (level == 0) {
86 return writer.writeAll(".{ ... }");
87 }
88 if (ty.zigTypeTag(mod) == .Struct) {
89 try writer.writeAll(".{");
90 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
91
92 var i: u32 = 0;
93 while (i < max_len) : (i += 1) {
94 if (i != 0) try writer.writeAll(", ");
95 switch (ty.tag()) {
96 .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
97 else => {},
98 }
99 try print(.{
100 .ty = ty.structFieldType(i),
101 .val = try val.fieldValue(ty, mod, i),
102 }, writer, level - 1, mod);
103 }
104 if (ty.structFieldCount() > max_aggregate_items) {
105 try writer.writeAll(", ...");
106 }
107 return writer.writeAll("}");
108 } else {
109 const elem_ty = ty.elemType2(mod);
110 const len = ty.arrayLen(mod);
111
112 if (elem_ty.eql(Type.u8, mod)) str: {
113 const max_len = @intCast(usize, std.math.min(len, max_string_len));
114 var buf: [max_string_len]u8 = undefined;
115
116 var i: u32 = 0;
117 while (i < max_len) : (i += 1) {
118 const elem = try val.fieldValue(ty, mod, i);
119 if (elem.isUndef()) break :str;
120 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
121 }
122
123 const truncated = if (len > max_string_len) " (truncated)" else "";
124 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
125 }
126
127 try writer.writeAll(".{ ");
128
129 const max_len = std.math.min(len, max_aggregate_items);
130 var i: u32 = 0;
131 while (i < max_len) : (i += 1) {
132 if (i != 0) try writer.writeAll(", ");
133 try print(.{
134 .ty = elem_ty,
135 .val = try val.fieldValue(ty, mod, i),
136 }, writer, level - 1, mod);
137 }
138 if (len > max_aggregate_items) {
139 try writer.writeAll(", ...");
140 }
141 return writer.writeAll(" }");
142 }
143 },
85 .aggregate => return printAggregate(ty, val, writer, level, mod),
14486 .@"union" => {
14587 if (level == 0) {
14688 return writer.writeAll(".{ ... }");
......@@ -426,3 +368,70 @@ pub fn print(
426368 },
427369 };
428370}
371
372fn printAggregate(
373 ty: Type,
374 val: Value,
375 writer: anytype,
376 level: u8,
377 mod: *Module,
378) (@TypeOf(writer).Error || Allocator.Error)!void {
379 if (level == 0) {
380 return writer.writeAll(".{ ... }");
381 }
382 if (ty.zigTypeTag(mod) == .Struct) {
383 try writer.writeAll(".{");
384 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
385
386 var i: u32 = 0;
387 while (i < max_len) : (i += 1) {
388 if (i != 0) try writer.writeAll(", ");
389 switch (ty.tag()) {
390 .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
391 else => {},
392 }
393 try print(.{
394 .ty = ty.structFieldType(i),
395 .val = try val.fieldValue(ty, mod, i),
396 }, writer, level - 1, mod);
397 }
398 if (ty.structFieldCount() > max_aggregate_items) {
399 try writer.writeAll(", ...");
400 }
401 return writer.writeAll("}");
402 } else {
403 const elem_ty = ty.elemType2(mod);
404 const len = ty.arrayLen(mod);
405
406 if (elem_ty.eql(Type.u8, mod)) str: {
407 const max_len = @intCast(usize, std.math.min(len, max_string_len));
408 var buf: [max_string_len]u8 = undefined;
409
410 var i: u32 = 0;
411 while (i < max_len) : (i += 1) {
412 const elem = try val.fieldValue(ty, mod, i);
413 if (elem.isUndef()) break :str;
414 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
415 }
416
417 const truncated = if (len > max_string_len) " (truncated)" else "";
418 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
419 }
420
421 try writer.writeAll(".{ ");
422
423 const max_len = std.math.min(len, max_aggregate_items);
424 var i: u32 = 0;
425 while (i < max_len) : (i += 1) {
426 if (i != 0) try writer.writeAll(", ");
427 try print(.{
428 .ty = elem_ty,
429 .val = try val.fieldValue(ty, mod, i),
430 }, writer, level - 1, mod);
431 }
432 if (len > max_aggregate_items) {
433 try writer.writeAll(", ...");
434 }
435 return writer.writeAll(" }");
436 }
437}
src/codegen/c.zig+12-1
......@@ -1127,8 +1127,19 @@ pub const DeclGen = struct {
11271127 try writer.writeByte('}');
11281128 return;
11291129 },
1130 .empty_struct => {
1131 const ai = ty.arrayInfo(mod);
1132 try writer.writeByte('{');
1133 if (ai.sentinel) |s| {
1134 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1135 } else {
1136 try writer.writeByte('0');
1137 }
1138 try writer.writeByte('}');
1139 return;
1140 },
11301141 .none => switch (val.tag()) {
1131 .empty_struct_value, .empty_array => {
1142 .empty_array => {
11321143 const ai = ty.arrayInfo(mod);
11331144 try writer.writeByte('{');
11341145 if (ai.sentinel) |s| {
src/type.zig+1464-1444
......@@ -34,8 +34,51 @@ pub const Type = struct {
3434 }
3535
3636 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
37 if (ty.ip_index != .none) {
38 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
37 switch (ty.ip_index) {
38 .none => switch (ty.tag()) {
39 .error_set,
40 .error_set_single,
41 .error_set_inferred,
42 .error_set_merged,
43 => return .ErrorSet,
44
45 .@"opaque" => return .Opaque,
46
47 .function => return .Fn,
48
49 .array,
50 .array_sentinel,
51 => return .Array,
52
53 .pointer,
54 .inferred_alloc_const,
55 .inferred_alloc_mut,
56 => return .Pointer,
57
58 .optional => return .Optional,
59
60 .error_union => return .ErrorUnion,
61
62 .anyframe_T => return .AnyFrame,
63
64 .empty_struct,
65 .@"struct",
66 .tuple,
67 .anon_struct,
68 => return .Struct,
69
70 .enum_full,
71 .enum_nonexhaustive,
72 .enum_simple,
73 .enum_numbered,
74 => return .Enum,
75
76 .@"union",
77 .union_safety_tagged,
78 .union_tagged,
79 => return .Union,
80 },
81 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3982 .int_type => return .Int,
4083 .ptr_type => return .Pointer,
4184 .array_type => return .Array,
......@@ -104,51 +147,7 @@ pub const Type = struct {
104147 .enum_tag,
105148 .simple_value,
106149 => unreachable, // it's a value, not a type
107 }
108 }
109 switch (ty.tag()) {
110 .error_set,
111 .error_set_single,
112 .error_set_inferred,
113 .error_set_merged,
114 => return .ErrorSet,
115
116 .@"opaque" => return .Opaque,
117
118 .function => return .Fn,
119
120 .array,
121 .array_sentinel,
122 => return .Array,
123
124 .pointer,
125 .inferred_alloc_const,
126 .inferred_alloc_mut,
127 => return .Pointer,
128
129 .optional => return .Optional,
130
131 .error_union => return .ErrorUnion,
132
133 .anyframe_T => return .AnyFrame,
134
135 .empty_struct,
136 .empty_struct_literal,
137 .@"struct",
138 .tuple,
139 .anon_struct,
140 => return .Struct,
141
142 .enum_full,
143 .enum_nonexhaustive,
144 .enum_simple,
145 .enum_numbered,
146 => return .Enum,
147
148 .@"union",
149 .union_safety_tagged,
150 .union_tagged,
151 => return .Union,
150 },
152151 }
153152 }
154153
......@@ -517,7 +516,7 @@ pub const Type = struct {
517516 const b_struct_obj = (b.castTag(.@"struct") orelse return false).data;
518517 return a_struct_obj == b_struct_obj;
519518 },
520 .tuple, .empty_struct_literal => {
519 .tuple => {
521520 if (!b.isSimpleTuple()) return false;
522521
523522 const a_tuple = a.tupleFields();
......@@ -741,7 +740,7 @@ pub const Type = struct {
741740 const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data;
742741 std.hash.autoHash(hasher, struct_obj);
743742 },
744 .tuple, .empty_struct_literal => {
743 .tuple => {
745744 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
746745
747746 const tuple = ty.tupleFields();
......@@ -837,7 +836,6 @@ pub const Type = struct {
837836 } else switch (self.legacy.ptr_otherwise.tag) {
838837 .inferred_alloc_const,
839838 .inferred_alloc_mut,
840 .empty_struct_literal,
841839 => unreachable,
842840
843841 .optional,
......@@ -1047,7 +1045,7 @@ pub const Type = struct {
10471045 while (true) {
10481046 const t = ty.tag();
10491047 switch (t) {
1050 .empty_struct, .empty_struct_literal => return writer.writeAll("struct {}"),
1048 .empty_struct => return writer.writeAll("struct {}"),
10511049
10521050 .@"struct" => {
10531051 const struct_obj = ty.castTag(.@"struct").?.data;
......@@ -1266,327 +1264,328 @@ pub const Type = struct {
12661264
12671265 /// Prints a name suitable for `@typeName`.
12681266 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
1269 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1270 .int_type => |int_type| {
1271 const sign_char: u8 = switch (int_type.signedness) {
1272 .signed => 'i',
1273 .unsigned => 'u',
1274 };
1275 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
1276 },
1277 .ptr_type => {
1278 const info = ty.ptrInfo(mod);
1279
1280 if (info.sentinel) |s| switch (info.size) {
1281 .One, .C => unreachable,
1282 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1283 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1284 } else switch (info.size) {
1285 .One => try writer.writeAll("*"),
1286 .Many => try writer.writeAll("[*]"),
1287 .C => try writer.writeAll("[*c]"),
1288 .Slice => try writer.writeAll("[]"),
1289 }
1290 if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
1291 if (info.@"align" != 0) {
1292 try writer.print("align({d}", .{info.@"align"});
1293 } else {
1294 const alignment = info.pointee_type.abiAlignment(mod);
1295 try writer.print("align({d}", .{alignment});
1296 }
1297
1298 if (info.bit_offset != 0 or info.host_size != 0) {
1299 try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });
1300 }
1301 if (info.vector_index == .runtime) {
1302 try writer.writeAll(":?");
1303 } else if (info.vector_index != .none) {
1304 try writer.print(":{d}", .{@enumToInt(info.vector_index)});
1305 }
1306 try writer.writeAll(") ");
1307 }
1308 if (info.@"addrspace" != .generic) {
1309 try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});
1310 }
1311 if (!info.mutable) try writer.writeAll("const ");
1312 if (info.@"volatile") try writer.writeAll("volatile ");
1313 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
1314
1315 try print(info.pointee_type, writer, mod);
1316 return;
1317 },
1318 .array_type => |array_type| {
1319 if (array_type.sentinel == .none) {
1320 try writer.print("[{d}]", .{array_type.len});
1321 try print(array_type.child.toType(), writer, mod);
1322 } else {
1323 try writer.print("[{d}:{}]", .{
1324 array_type.len,
1325 array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod),
1326 });
1327 try print(array_type.child.toType(), writer, mod);
1328 }
1329 return;
1330 },
1331 .vector_type => |vector_type| {
1332 try writer.print("@Vector({d}, ", .{vector_type.len});
1333 try print(vector_type.child.toType(), writer, mod);
1334 try writer.writeAll(")");
1335 return;
1336 },
1337 .opt_type => |child| {
1338 try writer.writeByte('?');
1339 try print(child.toType(), writer, mod);
1340 return;
1341 },
1342 .error_union_type => |error_union_type| {
1343 try print(error_union_type.error_set_type.toType(), writer, mod);
1344 try writer.writeByte('!');
1345 try print(error_union_type.payload_type.toType(), writer, mod);
1346 return;
1347 },
1348 .simple_type => |s| return writer.writeAll(@tagName(s)),
1349 .struct_type => @panic("TODO"),
1350 .union_type => @panic("TODO"),
1351 .simple_value => unreachable,
1352 .extern_func => unreachable,
1353 .int => unreachable,
1354 .enum_tag => unreachable,
1355 };
1356 const t = ty.tag();
1357 switch (t) {
1358 .inferred_alloc_const => unreachable,
1359 .inferred_alloc_mut => unreachable,
1267 switch (ty.ip_index) {
1268 .empty_struct_type => try writer.writeAll("@TypeOf(.{})"),
13601269
1361 .empty_struct_literal => try writer.writeAll("@TypeOf(.{})"),
1270 .none => switch (ty.tag()) {
1271 .inferred_alloc_const => unreachable,
1272 .inferred_alloc_mut => unreachable,
13621273
1363 .empty_struct => {
1364 const namespace = ty.castTag(.empty_struct).?.data;
1365 try namespace.renderFullyQualifiedName(mod, "", writer);
1366 },
1274 .empty_struct => {
1275 const namespace = ty.castTag(.empty_struct).?.data;
1276 try namespace.renderFullyQualifiedName(mod, "", writer);
1277 },
13671278
1368 .@"struct" => {
1369 const struct_obj = ty.castTag(.@"struct").?.data;
1370 const decl = mod.declPtr(struct_obj.owner_decl);
1371 try decl.renderFullyQualifiedName(mod, writer);
1372 },
1373 .@"union", .union_safety_tagged, .union_tagged => {
1374 const union_obj = ty.cast(Payload.Union).?.data;
1375 const decl = mod.declPtr(union_obj.owner_decl);
1376 try decl.renderFullyQualifiedName(mod, writer);
1377 },
1378 .enum_full, .enum_nonexhaustive => {
1379 const enum_full = ty.cast(Payload.EnumFull).?.data;
1380 const decl = mod.declPtr(enum_full.owner_decl);
1381 try decl.renderFullyQualifiedName(mod, writer);
1382 },
1383 .enum_simple => {
1384 const enum_simple = ty.castTag(.enum_simple).?.data;
1385 const decl = mod.declPtr(enum_simple.owner_decl);
1386 try decl.renderFullyQualifiedName(mod, writer);
1387 },
1388 .enum_numbered => {
1389 const enum_numbered = ty.castTag(.enum_numbered).?.data;
1390 const decl = mod.declPtr(enum_numbered.owner_decl);
1391 try decl.renderFullyQualifiedName(mod, writer);
1392 },
1393 .@"opaque" => {
1394 const opaque_obj = ty.cast(Payload.Opaque).?.data;
1395 const decl = mod.declPtr(opaque_obj.owner_decl);
1396 try decl.renderFullyQualifiedName(mod, writer);
1397 },
1279 .@"struct" => {
1280 const struct_obj = ty.castTag(.@"struct").?.data;
1281 const decl = mod.declPtr(struct_obj.owner_decl);
1282 try decl.renderFullyQualifiedName(mod, writer);
1283 },
1284 .@"union", .union_safety_tagged, .union_tagged => {
1285 const union_obj = ty.cast(Payload.Union).?.data;
1286 const decl = mod.declPtr(union_obj.owner_decl);
1287 try decl.renderFullyQualifiedName(mod, writer);
1288 },
1289 .enum_full, .enum_nonexhaustive => {
1290 const enum_full = ty.cast(Payload.EnumFull).?.data;
1291 const decl = mod.declPtr(enum_full.owner_decl);
1292 try decl.renderFullyQualifiedName(mod, writer);
1293 },
1294 .enum_simple => {
1295 const enum_simple = ty.castTag(.enum_simple).?.data;
1296 const decl = mod.declPtr(enum_simple.owner_decl);
1297 try decl.renderFullyQualifiedName(mod, writer);
1298 },
1299 .enum_numbered => {
1300 const enum_numbered = ty.castTag(.enum_numbered).?.data;
1301 const decl = mod.declPtr(enum_numbered.owner_decl);
1302 try decl.renderFullyQualifiedName(mod, writer);
1303 },
1304 .@"opaque" => {
1305 const opaque_obj = ty.cast(Payload.Opaque).?.data;
1306 const decl = mod.declPtr(opaque_obj.owner_decl);
1307 try decl.renderFullyQualifiedName(mod, writer);
1308 },
13981309
1399 .error_set_inferred => {
1400 const func = ty.castTag(.error_set_inferred).?.data.func;
1310 .error_set_inferred => {
1311 const func = ty.castTag(.error_set_inferred).?.data.func;
14011312
1402 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
1403 const owner_decl = mod.declPtr(func.owner_decl);
1404 try owner_decl.renderFullyQualifiedName(mod, writer);
1405 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
1406 },
1313 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
1314 const owner_decl = mod.declPtr(func.owner_decl);
1315 try owner_decl.renderFullyQualifiedName(mod, writer);
1316 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
1317 },
14071318
1408 .function => {
1409 const fn_info = ty.fnInfo();
1410 if (fn_info.is_noinline) {
1411 try writer.writeAll("noinline ");
1412 }
1413 try writer.writeAll("fn(");
1414 for (fn_info.param_types, 0..) |param_ty, i| {
1415 if (i != 0) try writer.writeAll(", ");
1416 if (fn_info.paramIsComptime(i)) {
1417 try writer.writeAll("comptime ");
1319 .function => {
1320 const fn_info = ty.fnInfo();
1321 if (fn_info.is_noinline) {
1322 try writer.writeAll("noinline ");
14181323 }
1419 if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) {
1420 try writer.writeAll("noalias ");
1421 };
1422 if (param_ty.isGenericPoison()) {
1423 try writer.writeAll("anytype");
1424 } else {
1425 try print(param_ty, writer, mod);
1324 try writer.writeAll("fn(");
1325 for (fn_info.param_types, 0..) |param_ty, i| {
1326 if (i != 0) try writer.writeAll(", ");
1327 if (fn_info.paramIsComptime(i)) {
1328 try writer.writeAll("comptime ");
1329 }
1330 if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) {
1331 try writer.writeAll("noalias ");
1332 };
1333 if (param_ty.isGenericPoison()) {
1334 try writer.writeAll("anytype");
1335 } else {
1336 try print(param_ty, writer, mod);
1337 }
14261338 }
1427 }
1428 if (fn_info.is_var_args) {
1429 if (fn_info.param_types.len != 0) {
1430 try writer.writeAll(", ");
1339 if (fn_info.is_var_args) {
1340 if (fn_info.param_types.len != 0) {
1341 try writer.writeAll(", ");
1342 }
1343 try writer.writeAll("...");
14311344 }
1432 try writer.writeAll("...");
1433 }
1434 try writer.writeAll(") ");
1435 if (fn_info.alignment != 0) {
1436 try writer.print("align({d}) ", .{fn_info.alignment});
1437 }
1438 if (fn_info.cc != .Unspecified) {
1439 try writer.writeAll("callconv(.");
1440 try writer.writeAll(@tagName(fn_info.cc));
14411345 try writer.writeAll(") ");
1442 }
1443 if (fn_info.return_type.isGenericPoison()) {
1444 try writer.writeAll("anytype");
1445 } else {
1446 try print(fn_info.return_type, writer, mod);
1447 }
1448 },
1346 if (fn_info.alignment != 0) {
1347 try writer.print("align({d}) ", .{fn_info.alignment});
1348 }
1349 if (fn_info.cc != .Unspecified) {
1350 try writer.writeAll("callconv(.");
1351 try writer.writeAll(@tagName(fn_info.cc));
1352 try writer.writeAll(") ");
1353 }
1354 if (fn_info.return_type.isGenericPoison()) {
1355 try writer.writeAll("anytype");
1356 } else {
1357 try print(fn_info.return_type, writer, mod);
1358 }
1359 },
14491360
1450 .error_union => {
1451 const error_union = ty.castTag(.error_union).?.data;
1452 try print(error_union.error_set, writer, mod);
1453 try writer.writeAll("!");
1454 try print(error_union.payload, writer, mod);
1455 },
1361 .error_union => {
1362 const error_union = ty.castTag(.error_union).?.data;
1363 try print(error_union.error_set, writer, mod);
1364 try writer.writeAll("!");
1365 try print(error_union.payload, writer, mod);
1366 },
14561367
1457 .array => {
1458 const payload = ty.castTag(.array).?.data;
1459 try writer.print("[{d}]", .{payload.len});
1460 try print(payload.elem_type, writer, mod);
1461 },
1462 .array_sentinel => {
1463 const payload = ty.castTag(.array_sentinel).?.data;
1464 try writer.print("[{d}:{}]", .{
1465 payload.len,
1466 payload.sentinel.fmtValue(payload.elem_type, mod),
1467 });
1468 try print(payload.elem_type, writer, mod);
1469 },
1470 .tuple => {
1471 const tuple = ty.castTag(.tuple).?.data;
1368 .array => {
1369 const payload = ty.castTag(.array).?.data;
1370 try writer.print("[{d}]", .{payload.len});
1371 try print(payload.elem_type, writer, mod);
1372 },
1373 .array_sentinel => {
1374 const payload = ty.castTag(.array_sentinel).?.data;
1375 try writer.print("[{d}:{}]", .{
1376 payload.len,
1377 payload.sentinel.fmtValue(payload.elem_type, mod),
1378 });
1379 try print(payload.elem_type, writer, mod);
1380 },
1381 .tuple => {
1382 const tuple = ty.castTag(.tuple).?.data;
14721383
1473 try writer.writeAll("tuple{");
1474 for (tuple.types, 0..) |field_ty, i| {
1475 if (i != 0) try writer.writeAll(", ");
1476 const val = tuple.values[i];
1477 if (val.ip_index != .unreachable_value) {
1478 try writer.writeAll("comptime ");
1479 }
1480 try print(field_ty, writer, mod);
1481 if (val.ip_index != .unreachable_value) {
1482 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1384 try writer.writeAll("tuple{");
1385 for (tuple.types, 0..) |field_ty, i| {
1386 if (i != 0) try writer.writeAll(", ");
1387 const val = tuple.values[i];
1388 if (val.ip_index != .unreachable_value) {
1389 try writer.writeAll("comptime ");
1390 }
1391 try print(field_ty, writer, mod);
1392 if (val.ip_index != .unreachable_value) {
1393 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1394 }
14831395 }
1484 }
1485 try writer.writeAll("}");
1486 },
1487 .anon_struct => {
1488 const anon_struct = ty.castTag(.anon_struct).?.data;
1396 try writer.writeAll("}");
1397 },
1398 .anon_struct => {
1399 const anon_struct = ty.castTag(.anon_struct).?.data;
14891400
1490 try writer.writeAll("struct{");
1491 for (anon_struct.types, 0..) |field_ty, i| {
1492 if (i != 0) try writer.writeAll(", ");
1493 const val = anon_struct.values[i];
1494 if (val.ip_index != .unreachable_value) {
1495 try writer.writeAll("comptime ");
1496 }
1497 try writer.writeAll(anon_struct.names[i]);
1498 try writer.writeAll(": ");
1401 try writer.writeAll("struct{");
1402 for (anon_struct.types, 0..) |field_ty, i| {
1403 if (i != 0) try writer.writeAll(", ");
1404 const val = anon_struct.values[i];
1405 if (val.ip_index != .unreachable_value) {
1406 try writer.writeAll("comptime ");
1407 }
1408 try writer.writeAll(anon_struct.names[i]);
1409 try writer.writeAll(": ");
14991410
1500 try print(field_ty, writer, mod);
1411 try print(field_ty, writer, mod);
15011412
1502 if (val.ip_index != .unreachable_value) {
1503 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1413 if (val.ip_index != .unreachable_value) {
1414 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1415 }
15041416 }
1505 }
1506 try writer.writeAll("}");
1507 },
1417 try writer.writeAll("}");
1418 },
15081419
1509 .pointer => {
1510 const info = ty.ptrInfo(mod);
1420 .pointer => {
1421 const info = ty.ptrInfo(mod);
15111422
1512 if (info.sentinel) |s| switch (info.size) {
1513 .One, .C => unreachable,
1514 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1515 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1516 } else switch (info.size) {
1517 .One => try writer.writeAll("*"),
1518 .Many => try writer.writeAll("[*]"),
1519 .C => try writer.writeAll("[*c]"),
1520 .Slice => try writer.writeAll("[]"),
1521 }
1522 if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
1523 if (info.@"align" != 0) {
1524 try writer.print("align({d}", .{info.@"align"});
1525 } else {
1526 const alignment = info.pointee_type.abiAlignment(mod);
1527 try writer.print("align({d}", .{alignment});
1423 if (info.sentinel) |s| switch (info.size) {
1424 .One, .C => unreachable,
1425 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1426 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1427 } else switch (info.size) {
1428 .One => try writer.writeAll("*"),
1429 .Many => try writer.writeAll("[*]"),
1430 .C => try writer.writeAll("[*c]"),
1431 .Slice => try writer.writeAll("[]"),
15281432 }
1433 if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
1434 if (info.@"align" != 0) {
1435 try writer.print("align({d}", .{info.@"align"});
1436 } else {
1437 const alignment = info.pointee_type.abiAlignment(mod);
1438 try writer.print("align({d}", .{alignment});
1439 }
15291440
1530 if (info.bit_offset != 0 or info.host_size != 0) {
1531 try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });
1441 if (info.bit_offset != 0 or info.host_size != 0) {
1442 try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });
1443 }
1444 if (info.vector_index == .runtime) {
1445 try writer.writeAll(":?");
1446 } else if (info.vector_index != .none) {
1447 try writer.print(":{d}", .{@enumToInt(info.vector_index)});
1448 }
1449 try writer.writeAll(") ");
15321450 }
1533 if (info.vector_index == .runtime) {
1534 try writer.writeAll(":?");
1535 } else if (info.vector_index != .none) {
1536 try writer.print(":{d}", .{@enumToInt(info.vector_index)});
1451 if (info.@"addrspace" != .generic) {
1452 try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});
15371453 }
1538 try writer.writeAll(") ");
1539 }
1540 if (info.@"addrspace" != .generic) {
1541 try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});
1542 }
1543 if (!info.mutable) try writer.writeAll("const ");
1544 if (info.@"volatile") try writer.writeAll("volatile ");
1545 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
1546
1547 try print(info.pointee_type, writer, mod);
1548 },
1454 if (!info.mutable) try writer.writeAll("const ");
1455 if (info.@"volatile") try writer.writeAll("volatile ");
1456 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
15491457
1550 .optional => {
1551 const child_type = ty.castTag(.optional).?.data;
1552 try writer.writeByte('?');
1553 try print(child_type, writer, mod);
1554 },
1555 .anyframe_T => {
1556 const return_type = ty.castTag(.anyframe_T).?.data;
1557 try writer.print("anyframe->", .{});
1558 try print(return_type, writer, mod);
1559 },
1560 .error_set => {
1561 const names = ty.castTag(.error_set).?.data.names.keys();
1562 try writer.writeAll("error{");
1563 for (names, 0..) |name, i| {
1564 if (i != 0) try writer.writeByte(',');
1565 try writer.writeAll(name);
1566 }
1567 try writer.writeAll("}");
1568 },
1569 .error_set_single => {
1570 const name = ty.castTag(.error_set_single).?.data;
1571 return writer.print("error{{{s}}}", .{name});
1572 },
1573 .error_set_merged => {
1574 const names = ty.castTag(.error_set_merged).?.data.keys();
1575 try writer.writeAll("error{");
1576 for (names, 0..) |name, i| {
1577 if (i != 0) try writer.writeByte(',');
1578 try writer.writeAll(name);
1579 }
1580 try writer.writeAll("}");
1581 },
1582 }
1583 }
1458 try print(info.pointee_type, writer, mod);
1459 },
15841460
1585 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {
1586 if (self.ip_index != .none) return self.ip_index.toValue();
1587 switch (self.tag()) {
1588 .inferred_alloc_const => unreachable,
1589 .inferred_alloc_mut => unreachable,
1461 .optional => {
1462 const child_type = ty.castTag(.optional).?.data;
1463 try writer.writeByte('?');
1464 try print(child_type, writer, mod);
1465 },
1466 .anyframe_T => {
1467 const return_type = ty.castTag(.anyframe_T).?.data;
1468 try writer.print("anyframe->", .{});
1469 try print(return_type, writer, mod);
1470 },
1471 .error_set => {
1472 const names = ty.castTag(.error_set).?.data.names.keys();
1473 try writer.writeAll("error{");
1474 for (names, 0..) |name, i| {
1475 if (i != 0) try writer.writeByte(',');
1476 try writer.writeAll(name);
1477 }
1478 try writer.writeAll("}");
1479 },
1480 .error_set_single => {
1481 const name = ty.castTag(.error_set_single).?.data;
1482 return writer.print("error{{{s}}}", .{name});
1483 },
1484 .error_set_merged => {
1485 const names = ty.castTag(.error_set_merged).?.data.keys();
1486 try writer.writeAll("error{");
1487 for (names, 0..) |name, i| {
1488 if (i != 0) try writer.writeByte(',');
1489 try writer.writeAll(name);
1490 }
1491 try writer.writeAll("}");
1492 },
1493 },
1494 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1495 .int_type => |int_type| {
1496 const sign_char: u8 = switch (int_type.signedness) {
1497 .signed => 'i',
1498 .unsigned => 'u',
1499 };
1500 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
1501 },
1502 .ptr_type => {
1503 const info = ty.ptrInfo(mod);
1504
1505 if (info.sentinel) |s| switch (info.size) {
1506 .One, .C => unreachable,
1507 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1508 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1509 } else switch (info.size) {
1510 .One => try writer.writeAll("*"),
1511 .Many => try writer.writeAll("[*]"),
1512 .C => try writer.writeAll("[*c]"),
1513 .Slice => try writer.writeAll("[]"),
1514 }
1515 if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
1516 if (info.@"align" != 0) {
1517 try writer.print("align({d}", .{info.@"align"});
1518 } else {
1519 const alignment = info.pointee_type.abiAlignment(mod);
1520 try writer.print("align({d}", .{alignment});
1521 }
1522
1523 if (info.bit_offset != 0 or info.host_size != 0) {
1524 try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });
1525 }
1526 if (info.vector_index == .runtime) {
1527 try writer.writeAll(":?");
1528 } else if (info.vector_index != .none) {
1529 try writer.print(":{d}", .{@enumToInt(info.vector_index)});
1530 }
1531 try writer.writeAll(") ");
1532 }
1533 if (info.@"addrspace" != .generic) {
1534 try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});
1535 }
1536 if (!info.mutable) try writer.writeAll("const ");
1537 if (info.@"volatile") try writer.writeAll("volatile ");
1538 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
1539
1540 try print(info.pointee_type, writer, mod);
1541 return;
1542 },
1543 .array_type => |array_type| {
1544 if (array_type.sentinel == .none) {
1545 try writer.print("[{d}]", .{array_type.len});
1546 try print(array_type.child.toType(), writer, mod);
1547 } else {
1548 try writer.print("[{d}:{}]", .{
1549 array_type.len,
1550 array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod),
1551 });
1552 try print(array_type.child.toType(), writer, mod);
1553 }
1554 return;
1555 },
1556 .vector_type => |vector_type| {
1557 try writer.print("@Vector({d}, ", .{vector_type.len});
1558 try print(vector_type.child.toType(), writer, mod);
1559 try writer.writeAll(")");
1560 return;
1561 },
1562 .opt_type => |child| {
1563 try writer.writeByte('?');
1564 try print(child.toType(), writer, mod);
1565 return;
1566 },
1567 .error_union_type => |error_union_type| {
1568 try print(error_union_type.error_set_type.toType(), writer, mod);
1569 try writer.writeByte('!');
1570 try print(error_union_type.payload_type.toType(), writer, mod);
1571 return;
1572 },
1573 .simple_type => |s| return writer.writeAll(@tagName(s)),
1574 .struct_type => @panic("TODO"),
1575 .union_type => @panic("TODO"),
1576 .simple_value => unreachable,
1577 .extern_func => unreachable,
1578 .int => unreachable,
1579 .enum_tag => unreachable,
1580 },
1581 }
1582 }
1583
1584 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {
1585 if (self.ip_index != .none) return self.ip_index.toValue();
1586 switch (self.tag()) {
1587 .inferred_alloc_const => unreachable,
1588 .inferred_alloc_mut => unreachable,
15901589 else => return Value.Tag.ty.create(allocator, self),
15911590 }
15921591 }
......@@ -1610,240 +1609,244 @@ pub const Type = struct {
16101609 ignore_comptime_only: bool,
16111610 strat: AbiAlignmentAdvancedStrat,
16121611 ) RuntimeBitsError!bool {
1613 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1614 .int_type => |int_type| return int_type.bits != 0,
1615 .ptr_type => |ptr_type| {
1612 switch (ty.ip_index) {
1613 // False because it is a comptime-only type.
1614 .empty_struct_type => return false,
1615
1616 .none => switch (ty.tag()) {
1617 .error_set_inferred,
1618
1619 .@"opaque",
1620 .error_set_single,
1621 .error_union,
1622 .error_set,
1623 .error_set_merged,
1624 => return true,
1625
16161626 // Pointers to zero-bit types still have a runtime address; however, pointers
16171627 // to comptime-only types do not, with the exception of function pointers.
1618 if (ignore_comptime_only) return true;
1619 const child_ty = ptr_type.elem_type.toType();
1620 if (child_ty.zigTypeTag(mod) == .Fn) return !child_ty.fnInfo().is_generic;
1621 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
1622 return !comptimeOnly(ty, mod);
1623 },
1624 .array_type => |array_type| {
1625 if (array_type.sentinel != .none) {
1626 return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1627 } else {
1628 return array_type.len > 0 and
1629 try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1630 }
1631 },
1632 .vector_type => |vector_type| {
1633 return vector_type.len > 0 and
1634 try vector_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1635 },
1636 .opt_type => |child| {
1637 const child_ty = child.toType();
1638 if (child_ty.isNoReturn()) {
1639 // Then the optional is comptime-known to be null.
1640 return false;
1641 }
1642 if (ignore_comptime_only) {
1643 return true;
1644 } else if (strat == .sema) {
1645 return !(try strat.sema.typeRequiresComptime(child_ty));
1646 } else {
1647 return !comptimeOnly(child_ty, mod);
1648 }
1649 },
1650 .error_union_type => @panic("TODO"),
1651 .simple_type => |t| return switch (t) {
1652 .f16,
1653 .f32,
1654 .f64,
1655 .f80,
1656 .f128,
1657 .usize,
1658 .isize,
1659 .c_char,
1660 .c_short,
1661 .c_ushort,
1662 .c_int,
1663 .c_uint,
1664 .c_long,
1665 .c_ulong,
1666 .c_longlong,
1667 .c_ulonglong,
1668 .c_longdouble,
1669 .bool,
1670 .anyerror,
1671 .@"anyframe",
1672 .anyopaque,
1673 .atomic_order,
1674 .atomic_rmw_op,
1675 .calling_convention,
1676 .address_space,
1677 .float_mode,
1678 .reduce_op,
1679 .call_modifier,
1680 .prefetch_options,
1681 .export_options,
1682 .extern_options,
1683 => true,
1628 .anyframe_T,
1629 .pointer,
1630 => {
1631 if (ignore_comptime_only) {
1632 return true;
1633 } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) {
1634 return !ty.childType(mod).fnInfo().is_generic;
1635 } else if (strat == .sema) {
1636 return !(try strat.sema.typeRequiresComptime(ty));
1637 } else {
1638 return !comptimeOnly(ty, mod);
1639 }
1640 },
16841641
16851642 // These are false because they are comptime-only types.
1686 .void,
1687 .type,
1688 .comptime_int,
1689 .comptime_float,
1690 .noreturn,
1691 .null,
1692 .undefined,
1693 .enum_literal,
1694 .type_info,
1695 => false,
1643 .empty_struct,
1644 // These are function *bodies*, not pointers.
1645 // Special exceptions have to be made when emitting functions due to
1646 // this returning false.
1647 .function,
1648 => return false,
16961649
1697 .generic_poison => unreachable,
1698 .var_args_param => unreachable,
1699 },
1700 .struct_type => @panic("TODO"),
1701 .union_type => @panic("TODO"),
1702 .simple_value => unreachable,
1703 .extern_func => unreachable,
1704 .int => unreachable,
1705 .enum_tag => unreachable, // it's a value, not a type
1706 };
1707 switch (ty.tag()) {
1708 .error_set_inferred,
1709
1710 .@"opaque",
1711 .error_set_single,
1712 .error_union,
1713 .error_set,
1714 .error_set_merged,
1715 => return true,
1716
1717 // Pointers to zero-bit types still have a runtime address; however, pointers
1718 // to comptime-only types do not, with the exception of function pointers.
1719 .anyframe_T,
1720 .pointer,
1721 => {
1722 if (ignore_comptime_only) {
1723 return true;
1724 } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) {
1725 return !ty.childType(mod).fnInfo().is_generic;
1726 } else if (strat == .sema) {
1727 return !(try strat.sema.typeRequiresComptime(ty));
1728 } else {
1729 return !comptimeOnly(ty, mod);
1730 }
1731 },
1650 .optional => {
1651 const child_ty = ty.optionalChild(mod);
1652 if (child_ty.isNoReturn()) {
1653 // Then the optional is comptime-known to be null.
1654 return false;
1655 }
1656 if (ignore_comptime_only) {
1657 return true;
1658 } else if (strat == .sema) {
1659 return !(try strat.sema.typeRequiresComptime(child_ty));
1660 } else {
1661 return !comptimeOnly(child_ty, mod);
1662 }
1663 },
17321664
1733 // These are false because they are comptime-only types.
1734 .empty_struct,
1735 .empty_struct_literal,
1736 // These are function *bodies*, not pointers.
1737 // Special exceptions have to be made when emitting functions due to
1738 // this returning false.
1739 .function,
1740 => return false,
1665 .@"struct" => {
1666 const struct_obj = ty.castTag(.@"struct").?.data;
1667 if (struct_obj.status == .field_types_wip) {
1668 // In this case, we guess that hasRuntimeBits() for this type is true,
1669 // and then later if our guess was incorrect, we emit a compile error.
1670 struct_obj.assumed_runtime_bits = true;
1671 return true;
1672 }
1673 switch (strat) {
1674 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1675 .eager => assert(struct_obj.haveFieldTypes()),
1676 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
1677 }
1678 for (struct_obj.fields.values()) |field| {
1679 if (field.is_comptime) continue;
1680 if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1681 return true;
1682 } else {
1683 return false;
1684 }
1685 },
17411686
1742 .optional => {
1743 const child_ty = ty.optionalChild(mod);
1744 if (child_ty.isNoReturn()) {
1745 // Then the optional is comptime-known to be null.
1746 return false;
1747 }
1748 if (ignore_comptime_only) {
1749 return true;
1750 } else if (strat == .sema) {
1751 return !(try strat.sema.typeRequiresComptime(child_ty));
1752 } else {
1753 return !comptimeOnly(child_ty, mod);
1754 }
1755 },
1687 .enum_full => {
1688 const enum_full = ty.castTag(.enum_full).?.data;
1689 return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1690 },
1691 .enum_simple => {
1692 const enum_simple = ty.castTag(.enum_simple).?.data;
1693 return enum_simple.fields.count() >= 2;
1694 },
1695 .enum_numbered, .enum_nonexhaustive => {
1696 const int_tag_ty = try ty.intTagType(mod);
1697 return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1698 },
17561699
1757 .@"struct" => {
1758 const struct_obj = ty.castTag(.@"struct").?.data;
1759 if (struct_obj.status == .field_types_wip) {
1760 // In this case, we guess that hasRuntimeBits() for this type is true,
1761 // and then later if our guess was incorrect, we emit a compile error.
1762 struct_obj.assumed_runtime_bits = true;
1763 return true;
1764 }
1765 switch (strat) {
1766 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1767 .eager => assert(struct_obj.haveFieldTypes()),
1768 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
1769 }
1770 for (struct_obj.fields.values()) |field| {
1771 if (field.is_comptime) continue;
1772 if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1700 .@"union" => {
1701 const union_obj = ty.castTag(.@"union").?.data;
1702 if (union_obj.status == .field_types_wip) {
1703 // In this case, we guess that hasRuntimeBits() for this type is true,
1704 // and then later if our guess was incorrect, we emit a compile error.
1705 union_obj.assumed_runtime_bits = true;
17731706 return true;
1774 } else {
1775 return false;
1776 }
1777 },
1707 }
1708 switch (strat) {
1709 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1710 .eager => assert(union_obj.haveFieldTypes()),
1711 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
1712 }
1713 for (union_obj.fields.values()) |value| {
1714 if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1715 return true;
1716 } else {
1717 return false;
1718 }
1719 },
1720 .union_safety_tagged, .union_tagged => {
1721 const union_obj = ty.cast(Payload.Union).?.data;
1722 if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) {
1723 return true;
1724 }
17781725
1779 .enum_full => {
1780 const enum_full = ty.castTag(.enum_full).?.data;
1781 return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1782 },
1783 .enum_simple => {
1784 const enum_simple = ty.castTag(.enum_simple).?.data;
1785 return enum_simple.fields.count() >= 2;
1786 },
1787 .enum_numbered, .enum_nonexhaustive => {
1788 const int_tag_ty = try ty.intTagType(mod);
1789 return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1790 },
1726 switch (strat) {
1727 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1728 .eager => assert(union_obj.haveFieldTypes()),
1729 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
1730 }
1731 for (union_obj.fields.values()) |value| {
1732 if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1733 return true;
1734 } else {
1735 return false;
1736 }
1737 },
17911738
1792 .@"union" => {
1793 const union_obj = ty.castTag(.@"union").?.data;
1794 if (union_obj.status == .field_types_wip) {
1795 // In this case, we guess that hasRuntimeBits() for this type is true,
1796 // and then later if our guess was incorrect, we emit a compile error.
1797 union_obj.assumed_runtime_bits = true;
1798 return true;
1799 }
1800 switch (strat) {
1801 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1802 .eager => assert(union_obj.haveFieldTypes()),
1803 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
1804 }
1805 for (union_obj.fields.values()) |value| {
1806 if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1807 return true;
1808 } else {
1809 return false;
1810 }
1811 },
1812 .union_safety_tagged, .union_tagged => {
1813 const union_obj = ty.cast(Payload.Union).?.data;
1814 if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) {
1815 return true;
1816 }
1739 .array => return ty.arrayLen(mod) != 0 and
1740 try ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
1741 .array_sentinel => return ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
18171742
1818 switch (strat) {
1819 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1820 .eager => assert(union_obj.haveFieldTypes()),
1821 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
1822 }
1823 for (union_obj.fields.values()) |value| {
1824 if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1825 return true;
1826 } else {
1743 .tuple, .anon_struct => {
1744 const tuple = ty.tupleFields();
1745 for (tuple.types, 0..) |field_ty, i| {
1746 const val = tuple.values[i];
1747 if (val.ip_index != .unreachable_value) continue; // comptime field
1748 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
1749 }
18271750 return false;
1828 }
1829 },
1830
1831 .array => return ty.arrayLen(mod) != 0 and
1832 try ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
1833 .array_sentinel => return ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
1751 },
18341752
1835 .tuple, .anon_struct => {
1836 const tuple = ty.tupleFields();
1837 for (tuple.types, 0..) |field_ty, i| {
1838 const val = tuple.values[i];
1839 if (val.ip_index != .unreachable_value) continue; // comptime field
1840 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
1841 }
1842 return false;
1753 .inferred_alloc_const => unreachable,
1754 .inferred_alloc_mut => unreachable,
1755 },
1756 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1757 .int_type => |int_type| return int_type.bits != 0,
1758 .ptr_type => |ptr_type| {
1759 // Pointers to zero-bit types still have a runtime address; however, pointers
1760 // to comptime-only types do not, with the exception of function pointers.
1761 if (ignore_comptime_only) return true;
1762 const child_ty = ptr_type.elem_type.toType();
1763 if (child_ty.zigTypeTag(mod) == .Fn) return !child_ty.fnInfo().is_generic;
1764 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
1765 return !comptimeOnly(ty, mod);
1766 },
1767 .array_type => |array_type| {
1768 if (array_type.sentinel != .none) {
1769 return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1770 } else {
1771 return array_type.len > 0 and
1772 try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1773 }
1774 },
1775 .vector_type => |vector_type| {
1776 return vector_type.len > 0 and
1777 try vector_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1778 },
1779 .opt_type => |child| {
1780 const child_ty = child.toType();
1781 if (child_ty.isNoReturn()) {
1782 // Then the optional is comptime-known to be null.
1783 return false;
1784 }
1785 if (ignore_comptime_only) {
1786 return true;
1787 } else if (strat == .sema) {
1788 return !(try strat.sema.typeRequiresComptime(child_ty));
1789 } else {
1790 return !comptimeOnly(child_ty, mod);
1791 }
1792 },
1793 .error_union_type => @panic("TODO"),
1794 .simple_type => |t| return switch (t) {
1795 .f16,
1796 .f32,
1797 .f64,
1798 .f80,
1799 .f128,
1800 .usize,
1801 .isize,
1802 .c_char,
1803 .c_short,
1804 .c_ushort,
1805 .c_int,
1806 .c_uint,
1807 .c_long,
1808 .c_ulong,
1809 .c_longlong,
1810 .c_ulonglong,
1811 .c_longdouble,
1812 .bool,
1813 .anyerror,
1814 .@"anyframe",
1815 .anyopaque,
1816 .atomic_order,
1817 .atomic_rmw_op,
1818 .calling_convention,
1819 .address_space,
1820 .float_mode,
1821 .reduce_op,
1822 .call_modifier,
1823 .prefetch_options,
1824 .export_options,
1825 .extern_options,
1826 => true,
1827
1828 // These are false because they are comptime-only types.
1829 .void,
1830 .type,
1831 .comptime_int,
1832 .comptime_float,
1833 .noreturn,
1834 .null,
1835 .undefined,
1836 .enum_literal,
1837 .type_info,
1838 => false,
1839
1840 .generic_poison => unreachable,
1841 .var_args_param => unreachable,
1842 },
1843 .struct_type => @panic("TODO"),
1844 .union_type => @panic("TODO"),
1845 .simple_value => unreachable,
1846 .extern_func => unreachable,
1847 .int => unreachable,
1848 .enum_tag => unreachable, // it's a value, not a type
18431849 },
1844
1845 .inferred_alloc_const => unreachable,
1846 .inferred_alloc_mut => unreachable,
18471850 }
18481851 }
18491852
......@@ -1851,104 +1854,107 @@ pub const Type = struct {
18511854 /// readFrom/writeToMemory are supported only for types with a well-
18521855 /// defined memory layout
18531856 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
1854 if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1855 .int_type => true,
1856 .ptr_type => true,
1857 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
1858 .vector_type => true,
1859 .opt_type => |child| child.toType().isPtrLikeOptional(mod),
1860 .error_union_type => false,
1861 .simple_type => |t| switch (t) {
1862 .f16,
1863 .f32,
1864 .f64,
1865 .f80,
1866 .f128,
1867 .usize,
1868 .isize,
1869 .c_char,
1870 .c_short,
1871 .c_ushort,
1872 .c_int,
1873 .c_uint,
1874 .c_long,
1875 .c_ulong,
1876 .c_longlong,
1877 .c_ulonglong,
1878 .c_longdouble,
1879 .bool,
1880 .void,
1857 return switch (ty.ip_index) {
1858 .empty_struct_type => false,
1859
1860 .none => switch (ty.tag()) {
1861 .pointer,
1862 .enum_numbered,
18811863 => true,
18821864
1883 .anyerror,
1884 .@"anyframe",
1885 .anyopaque,
1886 .atomic_order,
1887 .atomic_rmw_op,
1888 .calling_convention,
1889 .address_space,
1890 .float_mode,
1891 .reduce_op,
1892 .call_modifier,
1893 .prefetch_options,
1894 .export_options,
1895 .extern_options,
1896 .type,
1897 .comptime_int,
1898 .comptime_float,
1899 .noreturn,
1900 .null,
1901 .undefined,
1902 .enum_literal,
1903 .type_info,
1904 .generic_poison,
1865 .error_set,
1866 .error_set_single,
1867 .error_set_inferred,
1868 .error_set_merged,
1869 .@"opaque",
1870 // These are function bodies, not function pointers.
1871 .function,
1872 .enum_simple,
1873 .error_union,
1874 .anyframe_T,
1875 .tuple,
1876 .anon_struct,
1877 .empty_struct,
19051878 => false,
19061879
1907 .var_args_param => unreachable,
1908 },
1909 .struct_type => @panic("TODO"),
1910 .union_type => @panic("TODO"),
1911 .simple_value => unreachable,
1912 .extern_func => unreachable,
1913 .int => unreachable,
1914 .enum_tag => unreachable, // it's a value, not a type
1915 };
1916 return switch (ty.tag()) {
1917 .pointer,
1918 .enum_numbered,
1919 => true,
1880 .enum_full,
1881 .enum_nonexhaustive,
1882 => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred,
19201883
1921 .error_set,
1922 .error_set_single,
1923 .error_set_inferred,
1924 .error_set_merged,
1925 .@"opaque",
1926 // These are function bodies, not function pointers.
1927 .function,
1928 .enum_simple,
1929 .error_union,
1930 .anyframe_T,
1931 .tuple,
1932 .anon_struct,
1933 .empty_struct_literal,
1934 .empty_struct,
1935 => false,
1884 .inferred_alloc_mut => unreachable,
1885 .inferred_alloc_const => unreachable,
19361886
1937 .enum_full,
1938 .enum_nonexhaustive,
1939 => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred,
1887 .array,
1888 .array_sentinel,
1889 => ty.childType(mod).hasWellDefinedLayout(mod),
19401890
1941 .inferred_alloc_mut => unreachable,
1942 .inferred_alloc_const => unreachable,
1891 .optional => ty.isPtrLikeOptional(mod),
1892 .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto,
1893 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,
1894 .union_tagged => false,
1895 },
1896 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1897 .int_type => true,
1898 .ptr_type => true,
1899 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
1900 .vector_type => true,
1901 .opt_type => |child| child.toType().isPtrLikeOptional(mod),
1902 .error_union_type => false,
1903 .simple_type => |t| switch (t) {
1904 .f16,
1905 .f32,
1906 .f64,
1907 .f80,
1908 .f128,
1909 .usize,
1910 .isize,
1911 .c_char,
1912 .c_short,
1913 .c_ushort,
1914 .c_int,
1915 .c_uint,
1916 .c_long,
1917 .c_ulong,
1918 .c_longlong,
1919 .c_ulonglong,
1920 .c_longdouble,
1921 .bool,
1922 .void,
1923 => true,
19431924
1944 .array,
1945 .array_sentinel,
1946 => ty.childType(mod).hasWellDefinedLayout(mod),
1925 .anyerror,
1926 .@"anyframe",
1927 .anyopaque,
1928 .atomic_order,
1929 .atomic_rmw_op,
1930 .calling_convention,
1931 .address_space,
1932 .float_mode,
1933 .reduce_op,
1934 .call_modifier,
1935 .prefetch_options,
1936 .export_options,
1937 .extern_options,
1938 .type,
1939 .comptime_int,
1940 .comptime_float,
1941 .noreturn,
1942 .null,
1943 .undefined,
1944 .enum_literal,
1945 .type_info,
1946 .generic_poison,
1947 => false,
19471948
1948 .optional => ty.isPtrLikeOptional(mod),
1949 .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto,
1950 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,
1951 .union_tagged => false,
1949 .var_args_param => unreachable,
1950 },
1951 .struct_type => @panic("TODO"),
1952 .union_type => @panic("TODO"),
1953 .simple_value => unreachable,
1954 .extern_func => unreachable,
1955 .int => unreachable,
1956 .enum_tag => unreachable, // it's a value, not a type
1957 },
19521958 };
19531959 }
19541960
......@@ -2120,232 +2126,232 @@ pub const Type = struct {
21202126 else => null,
21212127 };
21222128
2123 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2124 .int_type => |int_type| {
2125 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
2126 return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) };
2127 },
2128 .ptr_type => {
2129 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2130 },
2131 .array_type => |array_type| {
2132 return array_type.child.toType().abiAlignmentAdvanced(mod, strat);
2133 },
2134 .vector_type => |vector_type| {
2135 const bits_u64 = try bitSizeAdvanced(vector_type.child.toType(), mod, opt_sema);
2136 const bits = @intCast(u32, bits_u64);
2137 const bytes = ((bits * vector_type.len) + 7) / 8;
2138 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
2139 return AbiAlignmentAdvanced{ .scalar = alignment };
2140 },
2129 switch (ty.ip_index) {
2130 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },
2131 .none => switch (ty.tag()) {
2132 .@"opaque" => return AbiAlignmentAdvanced{ .scalar = 1 },
21412133
2142 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
2143 .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
2144 .simple_type => |t| switch (t) {
2145 .bool,
2146 .atomic_order,
2147 .atomic_rmw_op,
2148 .calling_convention,
2149 .address_space,
2150 .float_mode,
2151 .reduce_op,
2152 .call_modifier,
2153 .prefetch_options,
2154 .anyopaque,
2155 => return AbiAlignmentAdvanced{ .scalar = 1 },
2134 // represents machine code; not a pointer
2135 .function => {
2136 const alignment = ty.castTag(.function).?.data.alignment;
2137 if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment };
2138 return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) };
2139 },
21562140
2157 .usize,
2158 .isize,
2159 .export_options,
2160 .extern_options,
2161 .@"anyframe",
2141 .pointer,
2142 .anyframe_T,
21622143 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
21632144
2164 .c_char => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.char) },
2165 .c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) },
2166 .c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) },
2167 .c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) },
2168 .c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) },
2169 .c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) },
2170 .c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) },
2171 .c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) },
2172 .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) },
2173 .c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2174
2175 .f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
2176 .f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) },
2177 .f64 => switch (target.c_type_bit_size(.double)) {
2178 64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) },
2179 else => return AbiAlignmentAdvanced{ .scalar = 8 },
2180 },
2181 .f80 => switch (target.c_type_bit_size(.longdouble)) {
2182 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2183 else => {
2184 const u80_ty: Type = .{
2185 .ip_index = .u80_type,
2186 .legacy = undefined,
2187 };
2188 return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) };
2189 },
2190 },
2191 .f128 => switch (target.c_type_bit_size(.longdouble)) {
2192 128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2193 else => return AbiAlignmentAdvanced{ .scalar = 16 },
2194 },
2195
21962145 // TODO revisit this when we have the concept of the error tag type
2197 .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },
2198
2199 .void,
2200 .type,
2201 .comptime_int,
2202 .comptime_float,
2203 .null,
2204 .undefined,
2205 .enum_literal,
2206 .type_info,
2207 => return AbiAlignmentAdvanced{ .scalar = 0 },
2208
2209 .noreturn => unreachable,
2210 .generic_poison => unreachable,
2211 .var_args_param => unreachable,
2212 },
2213 .struct_type => @panic("TODO"),
2214 .union_type => @panic("TODO"),
2215 .simple_value => unreachable,
2216 .extern_func => unreachable,
2217 .int => unreachable,
2218 .enum_tag => unreachable, // it's a value, not a type
2219 };
2220
2221 switch (ty.tag()) {
2222 .@"opaque" => return AbiAlignmentAdvanced{ .scalar = 1 },
2223
2224 // represents machine code; not a pointer
2225 .function => {
2226 const alignment = ty.castTag(.function).?.data.alignment;
2227 if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment };
2228 return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) };
2229 },
2230
2231 .pointer,
2232 .anyframe_T,
2233 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2146 .error_set_inferred,
2147 .error_set_single,
2148 .error_set,
2149 .error_set_merged,
2150 => return AbiAlignmentAdvanced{ .scalar = 2 },
22342151
2235 // TODO revisit this when we have the concept of the error tag type
2236 .error_set_inferred,
2237 .error_set_single,
2238 .error_set,
2239 .error_set_merged,
2240 => return AbiAlignmentAdvanced{ .scalar = 2 },
2241
2242 .array, .array_sentinel => return ty.childType(mod).abiAlignmentAdvanced(mod, strat),
2152 .array, .array_sentinel => return ty.childType(mod).abiAlignmentAdvanced(mod, strat),
22432153
2244 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
2245 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
2154 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
2155 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
22462156
2247 .@"struct" => {
2248 const struct_obj = ty.castTag(.@"struct").?.data;
2249 if (opt_sema) |sema| {
2250 if (struct_obj.status == .field_types_wip) {
2251 // We'll guess "pointer-aligned", if the struct has an
2252 // underaligned pointer field then some allocations
2253 // might require explicit alignment.
2254 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2157 .@"struct" => {
2158 const struct_obj = ty.castTag(.@"struct").?.data;
2159 if (opt_sema) |sema| {
2160 if (struct_obj.status == .field_types_wip) {
2161 // We'll guess "pointer-aligned", if the struct has an
2162 // underaligned pointer field then some allocations
2163 // might require explicit alignment.
2164 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2165 }
2166 _ = try sema.resolveTypeFields(ty);
22552167 }
2256 _ = try sema.resolveTypeFields(ty);
2257 }
2258 if (!struct_obj.haveFieldTypes()) switch (strat) {
2259 .eager => unreachable, // struct layout not resolved
2260 .sema => unreachable, // handled above
2261 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2262 };
2263 if (struct_obj.layout == .Packed) {
2264 switch (strat) {
2265 .sema => |sema| try sema.resolveTypeLayout(ty),
2266 .lazy => |arena| {
2267 if (!struct_obj.haveLayout()) {
2268 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
2269 }
2270 },
2271 .eager => {},
2168 if (!struct_obj.haveFieldTypes()) switch (strat) {
2169 .eager => unreachable, // struct layout not resolved
2170 .sema => unreachable, // handled above
2171 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2172 };
2173 if (struct_obj.layout == .Packed) {
2174 switch (strat) {
2175 .sema => |sema| try sema.resolveTypeLayout(ty),
2176 .lazy => |arena| {
2177 if (!struct_obj.haveLayout()) {
2178 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
2179 }
2180 },
2181 .eager => {},
2182 }
2183 assert(struct_obj.haveLayout());
2184 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) };
22722185 }
2273 assert(struct_obj.haveLayout());
2274 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) };
2275 }
2276
2277 const fields = ty.structFields();
2278 var big_align: u32 = 0;
2279 for (fields.values()) |field| {
2280 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
2281 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
2282 else => |e| return e,
2283 })) continue;
22842186
2285 const field_align = if (field.abi_align != 0)
2286 field.abi_align
2287 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {
2288 .scalar => |a| a,
2289 .val => switch (strat) {
2290 .eager => unreachable, // struct layout not resolved
2291 .sema => unreachable, // handled above
2292 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2293 },
2294 };
2295 big_align = @max(big_align, field_align);
2187 const fields = ty.structFields();
2188 var big_align: u32 = 0;
2189 for (fields.values()) |field| {
2190 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
2191 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
2192 else => |e| return e,
2193 })) continue;
2194
2195 const field_align = if (field.abi_align != 0)
2196 field.abi_align
2197 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {
2198 .scalar => |a| a,
2199 .val => switch (strat) {
2200 .eager => unreachable, // struct layout not resolved
2201 .sema => unreachable, // handled above
2202 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2203 },
2204 };
2205 big_align = @max(big_align, field_align);
2206
2207 // This logic is duplicated in Module.Struct.Field.alignment.
2208 if (struct_obj.layout == .Extern or target.ofmt == .c) {
2209 if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
2210 // The C ABI requires 128 bit integer fields of structs
2211 // to be 16-bytes aligned.
2212 big_align = @max(big_align, 16);
2213 }
2214 }
2215 }
2216 return AbiAlignmentAdvanced{ .scalar = big_align };
2217 },
22962218
2297 // This logic is duplicated in Module.Struct.Field.alignment.
2298 if (struct_obj.layout == .Extern or target.ofmt == .c) {
2299 if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
2300 // The C ABI requires 128 bit integer fields of structs
2301 // to be 16-bytes aligned.
2302 big_align = @max(big_align, 16);
2219 .tuple, .anon_struct => {
2220 const tuple = ty.tupleFields();
2221 var big_align: u32 = 0;
2222 for (tuple.types, 0..) |field_ty, i| {
2223 const val = tuple.values[i];
2224 if (val.ip_index != .unreachable_value) continue; // comptime field
2225 if (!(field_ty.hasRuntimeBits(mod))) continue;
2226
2227 switch (try field_ty.abiAlignmentAdvanced(mod, strat)) {
2228 .scalar => |field_align| big_align = @max(big_align, field_align),
2229 .val => switch (strat) {
2230 .eager => unreachable, // field type alignment not resolved
2231 .sema => unreachable, // passed to abiAlignmentAdvanced above
2232 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2233 },
23032234 }
23042235 }
2305 }
2306 return AbiAlignmentAdvanced{ .scalar = big_align };
2307 },
2236 return AbiAlignmentAdvanced{ .scalar = big_align };
2237 },
23082238
2309 .tuple, .anon_struct => {
2310 const tuple = ty.tupleFields();
2311 var big_align: u32 = 0;
2312 for (tuple.types, 0..) |field_ty, i| {
2313 const val = tuple.values[i];
2314 if (val.ip_index != .unreachable_value) continue; // comptime field
2315 if (!(field_ty.hasRuntimeBits(mod))) continue;
2239 .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => {
2240 const int_tag_ty = try ty.intTagType(mod);
2241 return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) };
2242 },
2243 .@"union" => {
2244 const union_obj = ty.castTag(.@"union").?.data;
2245 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, false);
2246 },
2247 .union_safety_tagged, .union_tagged => {
2248 const union_obj = ty.cast(Payload.Union).?.data;
2249 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true);
2250 },
2251
2252 .empty_struct => return AbiAlignmentAdvanced{ .scalar = 0 },
23162253
2317 switch (try field_ty.abiAlignmentAdvanced(mod, strat)) {
2318 .scalar => |field_align| big_align = @max(big_align, field_align),
2319 .val => switch (strat) {
2320 .eager => unreachable, // field type alignment not resolved
2321 .sema => unreachable, // passed to abiAlignmentAdvanced above
2322 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2323 },
2324 }
2325 }
2326 return AbiAlignmentAdvanced{ .scalar = big_align };
2254 .inferred_alloc_const,
2255 .inferred_alloc_mut,
2256 => unreachable,
23272257 },
2258 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2259 .int_type => |int_type| {
2260 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
2261 return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) };
2262 },
2263 .ptr_type => {
2264 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2265 },
2266 .array_type => |array_type| {
2267 return array_type.child.toType().abiAlignmentAdvanced(mod, strat);
2268 },
2269 .vector_type => |vector_type| {
2270 const bits_u64 = try bitSizeAdvanced(vector_type.child.toType(), mod, opt_sema);
2271 const bits = @intCast(u32, bits_u64);
2272 const bytes = ((bits * vector_type.len) + 7) / 8;
2273 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
2274 return AbiAlignmentAdvanced{ .scalar = alignment };
2275 },
23282276
2329 .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => {
2330 const int_tag_ty = try ty.intTagType(mod);
2331 return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) };
2332 },
2333 .@"union" => {
2334 const union_obj = ty.castTag(.@"union").?.data;
2335 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, false);
2336 },
2337 .union_safety_tagged, .union_tagged => {
2338 const union_obj = ty.cast(Payload.Union).?.data;
2339 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true);
2340 },
2277 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
2278 .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
2279 .simple_type => |t| switch (t) {
2280 .bool,
2281 .atomic_order,
2282 .atomic_rmw_op,
2283 .calling_convention,
2284 .address_space,
2285 .float_mode,
2286 .reduce_op,
2287 .call_modifier,
2288 .prefetch_options,
2289 .anyopaque,
2290 => return AbiAlignmentAdvanced{ .scalar = 1 },
23412291
2342 .empty_struct,
2343 .empty_struct_literal,
2344 => return AbiAlignmentAdvanced{ .scalar = 0 },
2292 .usize,
2293 .isize,
2294 .export_options,
2295 .extern_options,
2296 .@"anyframe",
2297 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2298
2299 .c_char => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.char) },
2300 .c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) },
2301 .c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) },
2302 .c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) },
2303 .c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) },
2304 .c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) },
2305 .c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) },
2306 .c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) },
2307 .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) },
2308 .c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2309
2310 .f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
2311 .f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) },
2312 .f64 => switch (target.c_type_bit_size(.double)) {
2313 64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) },
2314 else => return AbiAlignmentAdvanced{ .scalar = 8 },
2315 },
2316 .f80 => switch (target.c_type_bit_size(.longdouble)) {
2317 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2318 else => {
2319 const u80_ty: Type = .{
2320 .ip_index = .u80_type,
2321 .legacy = undefined,
2322 };
2323 return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) };
2324 },
2325 },
2326 .f128 => switch (target.c_type_bit_size(.longdouble)) {
2327 128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2328 else => return AbiAlignmentAdvanced{ .scalar = 16 },
2329 },
23452330
2346 .inferred_alloc_const,
2347 .inferred_alloc_mut,
2348 => unreachable,
2331 // TODO revisit this when we have the concept of the error tag type
2332 .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },
2333
2334 .void,
2335 .type,
2336 .comptime_int,
2337 .comptime_float,
2338 .null,
2339 .undefined,
2340 .enum_literal,
2341 .type_info,
2342 => return AbiAlignmentAdvanced{ .scalar = 0 },
2343
2344 .noreturn => unreachable,
2345 .generic_poison => unreachable,
2346 .var_args_param => unreachable,
2347 },
2348 .struct_type => @panic("TODO"),
2349 .union_type => @panic("TODO"),
2350 .simple_value => unreachable,
2351 .extern_func => unreachable,
2352 .int => unreachable,
2353 .enum_tag => unreachable, // it's a value, not a type
2354 },
23492355 }
23502356 }
23512357
......@@ -2506,255 +2512,256 @@ pub const Type = struct {
25062512 ) Module.CompileError!AbiSizeAdvanced {
25072513 const target = mod.getTarget();
25082514
2509 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2510 .int_type => |int_type| {
2511 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
2512 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
2513 },
2514 .ptr_type => |ptr_type| switch (ptr_type.size) {
2515 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
2516 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2517 },
2518 .array_type => |array_type| {
2519 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
2520 switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) {
2521 .scalar => |elem_size| return .{ .scalar = len * elem_size },
2522 .val => switch (strat) {
2523 .sema, .eager => unreachable,
2524 .lazy => |arena| return .{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2525 },
2526 }
2527 },
2528 .vector_type => |vector_type| {
2529 const opt_sema = switch (strat) {
2530 .sema => |sema| sema,
2531 .eager => null,
2532 .lazy => |arena| return AbiSizeAdvanced{
2533 .val = try Value.Tag.lazy_size.create(arena, ty),
2534 },
2535 };
2536 const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema);
2537 const elem_bits = @intCast(u32, elem_bits_u64);
2538 const total_bits = elem_bits * vector_type.len;
2539 const total_bytes = (total_bits + 7) / 8;
2540 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
2541 .scalar => |x| x,
2542 .val => return AbiSizeAdvanced{
2543 .val = try Value.Tag.lazy_size.create(strat.lazy, ty),
2544 },
2545 };
2546 const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment);
2547 return AbiSizeAdvanced{ .scalar = result };
2548 },
2515 switch (ty.ip_index) {
2516 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
25492517
2550 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
2551 .error_union_type => @panic("TODO"),
2552 .simple_type => |t| switch (t) {
2553 .bool,
2554 .atomic_order,
2555 .atomic_rmw_op,
2556 .calling_convention,
2557 .address_space,
2558 .float_mode,
2559 .reduce_op,
2560 .call_modifier,
2561 => return AbiSizeAdvanced{ .scalar = 1 },
2562
2563 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
2564 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
2565 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
2566 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
2567 .f80 => switch (target.c_type_bit_size(.longdouble)) {
2568 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
2518 .none => switch (ty.tag()) {
2519 .function => unreachable, // represents machine code; not a pointer
2520 .@"opaque" => unreachable, // no size available
2521 .inferred_alloc_const => unreachable,
2522 .inferred_alloc_mut => unreachable,
2523
2524 .empty_struct => return AbiSizeAdvanced{ .scalar = 0 },
2525
2526 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {
2527 .Packed => {
2528 const struct_obj = ty.castTag(.@"struct").?.data;
2529 switch (strat) {
2530 .sema => |sema| try sema.resolveTypeLayout(ty),
2531 .lazy => |arena| {
2532 if (!struct_obj.haveLayout()) {
2533 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2534 }
2535 },
2536 .eager => {},
2537 }
2538 assert(struct_obj.haveLayout());
2539 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) };
2540 },
25692541 else => {
2570 const u80_ty: Type = .{
2571 .ip_index = .u80_type,
2572 .legacy = undefined,
2573 };
2574 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };
2542 switch (strat) {
2543 .sema => |sema| try sema.resolveTypeLayout(ty),
2544 .lazy => |arena| {
2545 if (ty.castTag(.@"struct")) |payload| {
2546 const struct_obj = payload.data;
2547 if (!struct_obj.haveLayout()) {
2548 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2549 }
2550 }
2551 },
2552 .eager => {},
2553 }
2554 const field_count = ty.structFieldCount();
2555 if (field_count == 0) {
2556 return AbiSizeAdvanced{ .scalar = 0 };
2557 }
2558 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
25752559 },
25762560 },
25772561
2578 .usize,
2579 .isize,
2580 .@"anyframe",
2581 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2582
2583 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
2584 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
2585 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
2586 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
2587 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
2588 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
2589 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
2590 .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
2591 .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
2592 .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
2593
2594 .anyopaque,
2595 .void,
2596 .type,
2597 .comptime_int,
2598 .comptime_float,
2599 .null,
2600 .undefined,
2601 .enum_literal,
2602 => return AbiSizeAdvanced{ .scalar = 0 },
2603
2604 // TODO revisit this when we have the concept of the error tag type
2605 .anyerror => return AbiSizeAdvanced{ .scalar = 2 },
2606
2607 .prefetch_options => unreachable, // missing call to resolveTypeFields
2608 .export_options => unreachable, // missing call to resolveTypeFields
2609 .extern_options => unreachable, // missing call to resolveTypeFields
2610
2611 .type_info => unreachable,
2612 .noreturn => unreachable,
2613 .generic_poison => unreachable,
2614 .var_args_param => unreachable,
2615 },
2616 .struct_type => @panic("TODO"),
2617 .union_type => @panic("TODO"),
2618 .simple_value => unreachable,
2619 .extern_func => unreachable,
2620 .int => unreachable,
2621 .enum_tag => unreachable, // it's a value, not a type
2622 };
2623
2624 switch (ty.tag()) {
2625 .function => unreachable, // represents machine code; not a pointer
2626 .@"opaque" => unreachable, // no size available
2627 .inferred_alloc_const => unreachable,
2628 .inferred_alloc_mut => unreachable,
2629
2630 .empty_struct_literal,
2631 .empty_struct,
2632 => return AbiSizeAdvanced{ .scalar = 0 },
2562 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
2563 const int_tag_ty = try ty.intTagType(mod);
2564 return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) };
2565 },
2566 .@"union" => {
2567 const union_obj = ty.castTag(.@"union").?.data;
2568 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, false);
2569 },
2570 .union_safety_tagged, .union_tagged => {
2571 const union_obj = ty.cast(Payload.Union).?.data;
2572 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true);
2573 },
26332574
2634 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {
2635 .Packed => {
2636 const struct_obj = ty.castTag(.@"struct").?.data;
2637 switch (strat) {
2638 .sema => |sema| try sema.resolveTypeLayout(ty),
2639 .lazy => |arena| {
2640 if (!struct_obj.haveLayout()) {
2641 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2642 }
2575 .array => {
2576 const payload = ty.castTag(.array).?.data;
2577 switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) {
2578 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },
2579 .val => switch (strat) {
2580 .sema => unreachable,
2581 .eager => unreachable,
2582 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
26432583 },
2644 .eager => {},
26452584 }
2646 assert(struct_obj.haveLayout());
2647 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) };
26482585 },
2649 else => {
2650 switch (strat) {
2651 .sema => |sema| try sema.resolveTypeLayout(ty),
2652 .lazy => |arena| {
2653 if (ty.castTag(.@"struct")) |payload| {
2654 const struct_obj = payload.data;
2655 if (!struct_obj.haveLayout()) {
2656 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2657 }
2658 }
2586 .array_sentinel => {
2587 const payload = ty.castTag(.array_sentinel).?.data;
2588 switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) {
2589 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size },
2590 .val => switch (strat) {
2591 .sema => unreachable,
2592 .eager => unreachable,
2593 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
26592594 },
2660 .eager => {},
26612595 }
2662 const field_count = ty.structFieldCount();
2663 if (field_count == 0) {
2664 return AbiSizeAdvanced{ .scalar = 0 };
2665 }
2666 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
26672596 },
2668 },
26692597
2670 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
2671 const int_tag_ty = try ty.intTagType(mod);
2672 return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) };
2673 },
2674 .@"union" => {
2675 const union_obj = ty.castTag(.@"union").?.data;
2676 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, false);
2677 },
2678 .union_safety_tagged, .union_tagged => {
2679 const union_obj = ty.cast(Payload.Union).?.data;
2680 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true);
2681 },
2598 .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
26822599
2683 .array => {
2684 const payload = ty.castTag(.array).?.data;
2685 switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) {
2686 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },
2687 .val => switch (strat) {
2688 .sema => unreachable,
2689 .eager => unreachable,
2690 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2691 },
2692 }
2693 },
2694 .array_sentinel => {
2695 const payload = ty.castTag(.array_sentinel).?.data;
2696 switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) {
2697 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size },
2698 .val => switch (strat) {
2699 .sema => unreachable,
2700 .eager => unreachable,
2701 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2702 },
2703 }
2704 },
2600 .pointer => switch (ty.castTag(.pointer).?.data.size) {
2601 .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
2602 else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2603 },
27052604
2706 .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2605 // TODO revisit this when we have the concept of the error tag type
2606 .error_set_inferred,
2607 .error_set,
2608 .error_set_merged,
2609 .error_set_single,
2610 => return AbiSizeAdvanced{ .scalar = 2 },
27072611
2708 .pointer => switch (ty.castTag(.pointer).?.data.size) {
2709 .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
2710 else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2711 },
2612 .optional => return ty.abiSizeAdvancedOptional(mod, strat),
27122613
2713 // TODO revisit this when we have the concept of the error tag type
2714 .error_set_inferred,
2715 .error_set,
2716 .error_set_merged,
2717 .error_set_single,
2718 => return AbiSizeAdvanced{ .scalar = 2 },
2614 .error_union => {
2615 // This code needs to be kept in sync with the equivalent switch prong
2616 // in abiAlignmentAdvanced.
2617 const data = ty.castTag(.error_union).?.data;
2618 const code_size = abiSize(Type.anyerror, mod);
2619 if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
2620 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },
2621 else => |e| return e,
2622 })) {
2623 // Same as anyerror.
2624 return AbiSizeAdvanced{ .scalar = code_size };
2625 }
2626 const code_align = abiAlignment(Type.anyerror, mod);
2627 const payload_align = abiAlignment(data.payload, mod);
2628 const payload_size = switch (try data.payload.abiSizeAdvanced(mod, strat)) {
2629 .scalar => |elem_size| elem_size,
2630 .val => switch (strat) {
2631 .sema => unreachable,
2632 .eager => unreachable,
2633 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2634 },
2635 };
27192636
2720 .optional => return ty.abiSizeAdvancedOptional(mod, strat),
2637 var size: u64 = 0;
2638 if (code_align > payload_align) {
2639 size += code_size;
2640 size = std.mem.alignForwardGeneric(u64, size, payload_align);
2641 size += payload_size;
2642 size = std.mem.alignForwardGeneric(u64, size, code_align);
2643 } else {
2644 size += payload_size;
2645 size = std.mem.alignForwardGeneric(u64, size, code_align);
2646 size += code_size;
2647 size = std.mem.alignForwardGeneric(u64, size, payload_align);
2648 }
2649 return AbiSizeAdvanced{ .scalar = size };
2650 },
2651 },
2652 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
2653 .int_type => |int_type| {
2654 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
2655 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
2656 },
2657 .ptr_type => |ptr_type| switch (ptr_type.size) {
2658 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
2659 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2660 },
2661 .array_type => |array_type| {
2662 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
2663 switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) {
2664 .scalar => |elem_size| return .{ .scalar = len * elem_size },
2665 .val => switch (strat) {
2666 .sema, .eager => unreachable,
2667 .lazy => |arena| return .{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2668 },
2669 }
2670 },
2671 .vector_type => |vector_type| {
2672 const opt_sema = switch (strat) {
2673 .sema => |sema| sema,
2674 .eager => null,
2675 .lazy => |arena| return AbiSizeAdvanced{
2676 .val = try Value.Tag.lazy_size.create(arena, ty),
2677 },
2678 };
2679 const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema);
2680 const elem_bits = @intCast(u32, elem_bits_u64);
2681 const total_bits = elem_bits * vector_type.len;
2682 const total_bytes = (total_bits + 7) / 8;
2683 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
2684 .scalar => |x| x,
2685 .val => return AbiSizeAdvanced{
2686 .val = try Value.Tag.lazy_size.create(strat.lazy, ty),
2687 },
2688 };
2689 const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment);
2690 return AbiSizeAdvanced{ .scalar = result };
2691 },
27212692
2722 .error_union => {
2723 // This code needs to be kept in sync with the equivalent switch prong
2724 // in abiAlignmentAdvanced.
2725 const data = ty.castTag(.error_union).?.data;
2726 const code_size = abiSize(Type.anyerror, mod);
2727 if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
2728 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },
2729 else => |e| return e,
2730 })) {
2731 // Same as anyerror.
2732 return AbiSizeAdvanced{ .scalar = code_size };
2733 }
2734 const code_align = abiAlignment(Type.anyerror, mod);
2735 const payload_align = abiAlignment(data.payload, mod);
2736 const payload_size = switch (try data.payload.abiSizeAdvanced(mod, strat)) {
2737 .scalar => |elem_size| elem_size,
2738 .val => switch (strat) {
2739 .sema => unreachable,
2740 .eager => unreachable,
2741 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2693 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
2694 .error_union_type => @panic("TODO"),
2695 .simple_type => |t| switch (t) {
2696 .bool,
2697 .atomic_order,
2698 .atomic_rmw_op,
2699 .calling_convention,
2700 .address_space,
2701 .float_mode,
2702 .reduce_op,
2703 .call_modifier,
2704 => return AbiSizeAdvanced{ .scalar = 1 },
2705
2706 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
2707 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
2708 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
2709 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
2710 .f80 => switch (target.c_type_bit_size(.longdouble)) {
2711 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
2712 else => {
2713 const u80_ty: Type = .{
2714 .ip_index = .u80_type,
2715 .legacy = undefined,
2716 };
2717 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };
2718 },
27422719 },
2743 };
27442720
2745 var size: u64 = 0;
2746 if (code_align > payload_align) {
2747 size += code_size;
2748 size = std.mem.alignForwardGeneric(u64, size, payload_align);
2749 size += payload_size;
2750 size = std.mem.alignForwardGeneric(u64, size, code_align);
2751 } else {
2752 size += payload_size;
2753 size = std.mem.alignForwardGeneric(u64, size, code_align);
2754 size += code_size;
2755 size = std.mem.alignForwardGeneric(u64, size, payload_align);
2756 }
2757 return AbiSizeAdvanced{ .scalar = size };
2721 .usize,
2722 .isize,
2723 .@"anyframe",
2724 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2725
2726 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
2727 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
2728 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
2729 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
2730 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
2731 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
2732 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
2733 .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
2734 .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
2735 .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
2736
2737 .anyopaque,
2738 .void,
2739 .type,
2740 .comptime_int,
2741 .comptime_float,
2742 .null,
2743 .undefined,
2744 .enum_literal,
2745 => return AbiSizeAdvanced{ .scalar = 0 },
2746
2747 // TODO revisit this when we have the concept of the error tag type
2748 .anyerror => return AbiSizeAdvanced{ .scalar = 2 },
2749
2750 .prefetch_options => unreachable, // missing call to resolveTypeFields
2751 .export_options => unreachable, // missing call to resolveTypeFields
2752 .extern_options => unreachable, // missing call to resolveTypeFields
2753
2754 .type_info => unreachable,
2755 .noreturn => unreachable,
2756 .generic_poison => unreachable,
2757 .var_args_param => unreachable,
2758 },
2759 .struct_type => @panic("TODO"),
2760 .union_type => @panic("TODO"),
2761 .simple_value => unreachable,
2762 .extern_func => unreachable,
2763 .int => unreachable,
2764 .enum_tag => unreachable, // it's a value, not a type
27582765 },
27592766 }
27602767 }
......@@ -2929,7 +2936,6 @@ pub const Type = struct {
29292936 switch (ty.tag()) {
29302937 .function => unreachable, // represents machine code; not a pointer
29312938 .empty_struct => unreachable,
2932 .empty_struct_literal => unreachable,
29332939 .inferred_alloc_const => unreachable,
29342940 .inferred_alloc_mut => unreachable,
29352941 .@"opaque" => unreachable,
......@@ -3490,12 +3496,16 @@ pub const Type = struct {
34903496 }
34913497
34923498 pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout {
3493 return switch (ty.tag()) {
3494 .tuple, .empty_struct_literal, .anon_struct => .Auto,
3495 .@"struct" => ty.castTag(.@"struct").?.data.layout,
3496 .@"union" => ty.castTag(.@"union").?.data.layout,
3497 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,
3498 .union_tagged => ty.castTag(.union_tagged).?.data.layout,
3499 return switch (ty.ip_index) {
3500 .empty_struct_type => .Auto,
3501 .none => switch (ty.tag()) {
3502 .tuple, .anon_struct => .Auto,
3503 .@"struct" => ty.castTag(.@"struct").?.data.layout,
3504 .@"union" => ty.castTag(.@"union").?.data.layout,
3505 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,
3506 .union_tagged => ty.castTag(.union_tagged).?.data.layout,
3507 else => unreachable,
3508 },
34993509 else => unreachable,
35003510 };
35013511 }
......@@ -3610,13 +3620,14 @@ pub const Type = struct {
36103620
36113621 pub fn arrayLenIp(ty: Type, ip: InternPool) u64 {
36123622 return switch (ty.ip_index) {
3623 .empty_struct_type => 0,
36133624 .none => switch (ty.tag()) {
36143625 .array => ty.castTag(.array).?.data.len,
36153626 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,
36163627 .tuple => ty.castTag(.tuple).?.data.types.len,
36173628 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
36183629 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
3619 .empty_struct, .empty_struct_literal => 0,
3630 .empty_struct => 0,
36203631
36213632 else => unreachable,
36223633 },
......@@ -3649,10 +3660,10 @@ pub const Type = struct {
36493660 /// Asserts the type is an array, pointer or vector.
36503661 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
36513662 return switch (ty.ip_index) {
3663 .empty_struct_type => null,
36523664 .none => switch (ty.tag()) {
36533665 .array,
36543666 .tuple,
3655 .empty_struct_literal,
36563667 .@"struct",
36573668 => null,
36583669
......@@ -3951,197 +3962,200 @@ pub const Type = struct {
39513962 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
39523963 var ty = starting_type;
39533964
3954 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3955 .int_type => |int_type| {
3956 if (int_type.bits == 0) {
3957 return try mod.intValue(ty, 0);
3958 } else {
3959 return null;
3960 }
3961 },
3962 .ptr_type => return null,
3963 .array_type => |array_type| {
3964 if (array_type.len == 0)
3965 return Value.initTag(.empty_array);
3966 if ((try array_type.child.toType().onePossibleValue(mod)) != null)
3967 return Value.initTag(.the_only_possible_value);
3968 return null;
3969 },
3970 .vector_type => |vector_type| {
3971 if (vector_type.len == 0) return Value.initTag(.empty_array);
3972 if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v;
3973 return null;
3974 },
3975 .opt_type => |child| {
3976 if (child.toType().isNoReturn()) {
3977 return Value.null;
3978 } else {
3979 return null;
3980 }
3981 },
3982 .error_union_type => return null,
3983 .simple_type => |t| switch (t) {
3984 .f16,
3985 .f32,
3986 .f64,
3987 .f80,
3988 .f128,
3989 .usize,
3990 .isize,
3991 .c_char,
3992 .c_short,
3993 .c_ushort,
3994 .c_int,
3995 .c_uint,
3996 .c_long,
3997 .c_ulong,
3998 .c_longlong,
3999 .c_ulonglong,
4000 .c_longdouble,
4001 .anyopaque,
4002 .bool,
4003 .type,
4004 .anyerror,
4005 .comptime_int,
4006 .comptime_float,
4007 .@"anyframe",
4008 .enum_literal,
4009 .atomic_order,
4010 .atomic_rmw_op,
4011 .calling_convention,
4012 .address_space,
4013 .float_mode,
4014 .reduce_op,
4015 .call_modifier,
4016 .prefetch_options,
4017 .export_options,
4018 .extern_options,
4019 .type_info,
3965 while (true) switch (ty.ip_index) {
3966 .empty_struct_type => return Value.empty_struct,
3967
3968 .none => switch (ty.tag()) {
3969 .error_union,
3970 .error_set_single,
3971 .error_set,
3972 .error_set_merged,
3973 .function,
3974 .array_sentinel,
3975 .error_set_inferred,
3976 .@"opaque",
3977 .anyframe_T,
3978 .pointer,
40203979 => return null,
40213980
4022 .void => return Value.void,
4023 .noreturn => return Value.@"unreachable",
4024 .null => return Value.null,
4025 .undefined => return Value.undef,
3981 .optional => {
3982 const child_ty = ty.optionalChild(mod);
3983 if (child_ty.isNoReturn()) {
3984 return Value.null;
3985 } else {
3986 return null;
3987 }
3988 },
40263989
4027 .generic_poison => unreachable,
4028 .var_args_param => unreachable,
4029 },
4030 .struct_type => @panic("TODO"),
4031 .union_type => @panic("TODO"),
4032 .simple_value => unreachable,
4033 .extern_func => unreachable,
4034 .int => unreachable,
4035 .enum_tag => unreachable, // it's a value, not a type
4036 };
3990 .@"struct" => {
3991 const s = ty.castTag(.@"struct").?.data;
3992 assert(s.haveFieldTypes());
3993 for (s.fields.values()) |field| {
3994 if (field.is_comptime) continue;
3995 if ((try field.ty.onePossibleValue(mod)) != null) continue;
3996 return null;
3997 }
3998 return Value.empty_struct;
3999 },
40374000
4038 while (true) switch (ty.tag()) {
4039 .error_union,
4040 .error_set_single,
4041 .error_set,
4042 .error_set_merged,
4043 .function,
4044 .array_sentinel,
4045 .error_set_inferred,
4046 .@"opaque",
4047 .anyframe_T,
4048 .pointer,
4049 => return null,
4001 .tuple, .anon_struct => {
4002 const tuple = ty.tupleFields();
4003 for (tuple.values, 0..) |val, i| {
4004 const is_comptime = val.ip_index != .unreachable_value;
4005 if (is_comptime) continue;
4006 if ((try tuple.types[i].onePossibleValue(mod)) != null) continue;
4007 return null;
4008 }
4009 return Value.empty_struct;
4010 },
4011
4012 .enum_numbered => {
4013 const enum_numbered = ty.castTag(.enum_numbered).?.data;
4014 // An explicit tag type is always provided for enum_numbered.
4015 if (enum_numbered.tag_ty.hasRuntimeBits(mod)) {
4016 return null;
4017 }
4018 assert(enum_numbered.fields.count() == 1);
4019 return enum_numbered.values.keys()[0];
4020 },
4021 .enum_full => {
4022 const enum_full = ty.castTag(.enum_full).?.data;
4023 if (enum_full.tag_ty.hasRuntimeBits(mod)) {
4024 return null;
4025 }
4026 switch (enum_full.fields.count()) {
4027 0 => return Value.@"unreachable",
4028 1 => if (enum_full.values.count() == 0) {
4029 return try mod.intValue(ty, 0); // auto-numbered
4030 } else {
4031 return enum_full.values.keys()[0];
4032 },
4033 else => return null,
4034 }
4035 },
4036 .enum_simple => {
4037 const enum_simple = ty.castTag(.enum_simple).?.data;
4038 switch (enum_simple.fields.count()) {
4039 0 => return Value.@"unreachable",
4040 1 => return try mod.intValue(ty, 0),
4041 else => return null,
4042 }
4043 },
4044 .enum_nonexhaustive => {
4045 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
4046 if (!tag_ty.hasRuntimeBits(mod)) {
4047 return try mod.intValue(ty, 0);
4048 } else {
4049 return null;
4050 }
4051 },
4052 .@"union", .union_safety_tagged, .union_tagged => {
4053 const union_obj = ty.cast(Payload.Union).?.data;
4054 const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null;
4055 if (union_obj.fields.count() == 0) return Value.@"unreachable";
4056 const only_field = union_obj.fields.values()[0];
4057 const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null;
4058 _ = tag_val;
4059 _ = val_val;
4060 return Value.empty_struct;
4061 },
40504062
4051 .optional => {
4052 const child_ty = ty.optionalChild(mod);
4053 if (child_ty.isNoReturn()) {
4054 return Value.null;
4055 } else {
4056 return null;
4057 }
4058 },
4063 .empty_struct => return Value.empty_struct,
40594064
4060 .@"struct" => {
4061 const s = ty.castTag(.@"struct").?.data;
4062 assert(s.haveFieldTypes());
4063 for (s.fields.values()) |field| {
4064 if (field.is_comptime) continue;
4065 if ((try field.ty.onePossibleValue(mod)) != null) continue;
4065 .array => {
4066 if (ty.arrayLen(mod) == 0)
4067 return Value.initTag(.empty_array);
4068 if ((try ty.childType(mod).onePossibleValue(mod)) != null)
4069 return Value.initTag(.the_only_possible_value);
40664070 return null;
4067 }
4068 return Value.initTag(.empty_struct_value);
4069 },
4071 },
40704072
4071 .tuple, .anon_struct => {
4072 const tuple = ty.tupleFields();
4073 for (tuple.values, 0..) |val, i| {
4074 const is_comptime = val.ip_index != .unreachable_value;
4075 if (is_comptime) continue;
4076 if ((try tuple.types[i].onePossibleValue(mod)) != null) continue;
4077 return null;
4078 }
4079 return Value.initTag(.empty_struct_value);
4073 .inferred_alloc_const => unreachable,
4074 .inferred_alloc_mut => unreachable,
40804075 },
4081
4082 .enum_numbered => {
4083 const enum_numbered = ty.castTag(.enum_numbered).?.data;
4084 // An explicit tag type is always provided for enum_numbered.
4085 if (enum_numbered.tag_ty.hasRuntimeBits(mod)) {
4076 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4077 .int_type => |int_type| {
4078 if (int_type.bits == 0) {
4079 return try mod.intValue(ty, 0);
4080 } else {
4081 return null;
4082 }
4083 },
4084 .ptr_type => return null,
4085 .array_type => |array_type| {
4086 if (array_type.len == 0)
4087 return Value.initTag(.empty_array);
4088 if ((try array_type.child.toType().onePossibleValue(mod)) != null)
4089 return Value.initTag(.the_only_possible_value);
40864090 return null;
4087 }
4088 assert(enum_numbered.fields.count() == 1);
4089 return enum_numbered.values.keys()[0];
4090 },
4091 .enum_full => {
4092 const enum_full = ty.castTag(.enum_full).?.data;
4093 if (enum_full.tag_ty.hasRuntimeBits(mod)) {
4091 },
4092 .vector_type => |vector_type| {
4093 if (vector_type.len == 0) return Value.initTag(.empty_array);
4094 if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v;
40944095 return null;
4095 }
4096 switch (enum_full.fields.count()) {
4097 0 => return Value.@"unreachable",
4098 1 => if (enum_full.values.count() == 0) {
4099 return try mod.intValue(ty, 0); // auto-numbered
4096 },
4097 .opt_type => |child| {
4098 if (child.toType().isNoReturn()) {
4099 return Value.null;
41004100 } else {
4101 return enum_full.values.keys()[0];
4102 },
4103 else => return null,
4104 }
4105 },
4106 .enum_simple => {
4107 const enum_simple = ty.castTag(.enum_simple).?.data;
4108 switch (enum_simple.fields.count()) {
4109 0 => return Value.@"unreachable",
4110 1 => return try mod.intValue(ty, 0),
4111 else => return null,
4112 }
4113 },
4114 .enum_nonexhaustive => {
4115 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
4116 if (!tag_ty.hasRuntimeBits(mod)) {
4117 return try mod.intValue(ty, 0);
4118 } else {
4119 return null;
4120 }
4121 },
4122 .@"union", .union_safety_tagged, .union_tagged => {
4123 const union_obj = ty.cast(Payload.Union).?.data;
4124 const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null;
4125 if (union_obj.fields.count() == 0) return Value.@"unreachable";
4126 const only_field = union_obj.fields.values()[0];
4127 const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null;
4128 _ = tag_val;
4129 _ = val_val;
4130 return Value.initTag(.empty_struct_value);
4131 },
4101 return null;
4102 }
4103 },
4104 .error_union_type => return null,
4105 .simple_type => |t| switch (t) {
4106 .f16,
4107 .f32,
4108 .f64,
4109 .f80,
4110 .f128,
4111 .usize,
4112 .isize,
4113 .c_char,
4114 .c_short,
4115 .c_ushort,
4116 .c_int,
4117 .c_uint,
4118 .c_long,
4119 .c_ulong,
4120 .c_longlong,
4121 .c_ulonglong,
4122 .c_longdouble,
4123 .anyopaque,
4124 .bool,
4125 .type,
4126 .anyerror,
4127 .comptime_int,
4128 .comptime_float,
4129 .@"anyframe",
4130 .enum_literal,
4131 .atomic_order,
4132 .atomic_rmw_op,
4133 .calling_convention,
4134 .address_space,
4135 .float_mode,
4136 .reduce_op,
4137 .call_modifier,
4138 .prefetch_options,
4139 .export_options,
4140 .extern_options,
4141 .type_info,
4142 => return null,
41324143
4133 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
4144 .void => return Value.void,
4145 .noreturn => return Value.@"unreachable",
4146 .null => return Value.null,
4147 .undefined => return Value.undef,
41344148
4135 .array => {
4136 if (ty.arrayLen(mod) == 0)
4137 return Value.initTag(.empty_array);
4138 if ((try ty.childType(mod).onePossibleValue(mod)) != null)
4139 return Value.initTag(.the_only_possible_value);
4140 return null;
4149 .generic_poison => unreachable,
4150 .var_args_param => unreachable,
4151 },
4152 .struct_type => @panic("TODO"),
4153 .union_type => @panic("TODO"),
4154 .simple_value => unreachable,
4155 .extern_func => unreachable,
4156 .int => unreachable,
4157 .enum_tag => unreachable, // it's a value, not a type
41414158 },
4142
4143 .inferred_alloc_const => unreachable,
4144 .inferred_alloc_mut => unreachable,
41454159 };
41464160 }
41474161
......@@ -4150,159 +4164,161 @@ pub const Type = struct {
41504164 /// TODO merge these implementations together with the "advanced" pattern seen
41514165 /// elsewhere in this file.
41524166 pub fn comptimeOnly(ty: Type, mod: *const Module) bool {
4153 if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4154 .int_type => false,
4155 .ptr_type => |ptr_type| {
4156 const child_ty = ptr_type.elem_type.toType();
4157 if (child_ty.zigTypeTag(mod) == .Fn) {
4158 return false;
4159 } else {
4160 return child_ty.comptimeOnly(mod);
4161 }
4162 },
4163 .array_type => |array_type| array_type.child.toType().comptimeOnly(mod),
4164 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),
4165 .opt_type => |child| child.toType().comptimeOnly(mod),
4166 .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod),
4167 .simple_type => |t| switch (t) {
4168 .f16,
4169 .f32,
4170 .f64,
4171 .f80,
4172 .f128,
4173 .usize,
4174 .isize,
4175 .c_char,
4176 .c_short,
4177 .c_ushort,
4178 .c_int,
4179 .c_uint,
4180 .c_long,
4181 .c_ulong,
4182 .c_longlong,
4183 .c_ulonglong,
4184 .c_longdouble,
4185 .anyopaque,
4186 .bool,
4187 .void,
4188 .anyerror,
4189 .@"anyframe",
4190 .noreturn,
4191 .generic_poison,
4192 .atomic_order,
4193 .atomic_rmw_op,
4194 .calling_convention,
4195 .address_space,
4196 .float_mode,
4197 .reduce_op,
4198 .call_modifier,
4199 .prefetch_options,
4200 .export_options,
4201 .extern_options,
4202 => false,
4167 return switch (ty.ip_index) {
4168 .empty_struct_type => false,
42034169
4204 .type,
4205 .comptime_int,
4206 .comptime_float,
4207 .null,
4208 .undefined,
4209 .enum_literal,
4210 .type_info,
4211 => true,
4170 .none => switch (ty.tag()) {
4171 .empty_struct,
4172 .error_set,
4173 .error_set_single,
4174 .error_set_inferred,
4175 .error_set_merged,
4176 .@"opaque",
4177 .enum_simple,
4178 => false,
42124179
4213 .var_args_param => unreachable,
4214 },
4215 .struct_type => @panic("TODO"),
4216 .union_type => @panic("TODO"),
4217 .simple_value => unreachable,
4218 .extern_func => unreachable,
4219 .int => unreachable,
4220 .enum_tag => unreachable, // it's a value, not a type
4221 };
4180 // These are function bodies, not function pointers.
4181 .function => true,
42224182
4223 return switch (ty.tag()) {
4224 .empty_struct_literal,
4225 .empty_struct,
4226 .error_set,
4227 .error_set_single,
4228 .error_set_inferred,
4229 .error_set_merged,
4230 .@"opaque",
4231 .enum_simple,
4232 => false,
4183 .inferred_alloc_mut => unreachable,
4184 .inferred_alloc_const => unreachable,
42334185
4234 // These are function bodies, not function pointers.
4235 .function => true,
4186 .array,
4187 .array_sentinel,
4188 => return ty.childType(mod).comptimeOnly(mod),
42364189
4237 .inferred_alloc_mut => unreachable,
4238 .inferred_alloc_const => unreachable,
4190 .pointer => {
4191 const child_ty = ty.childType(mod);
4192 if (child_ty.zigTypeTag(mod) == .Fn) {
4193 return false;
4194 } else {
4195 return child_ty.comptimeOnly(mod);
4196 }
4197 },
42394198
4240 .array,
4241 .array_sentinel,
4242 => return ty.childType(mod).comptimeOnly(mod),
4199 .optional => {
4200 return ty.optionalChild(mod).comptimeOnly(mod);
4201 },
42434202
4244 .pointer => {
4245 const child_ty = ty.childType(mod);
4246 if (child_ty.zigTypeTag(mod) == .Fn) {
4203 .tuple, .anon_struct => {
4204 const tuple = ty.tupleFields();
4205 for (tuple.types, 0..) |field_ty, i| {
4206 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
4207 if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true;
4208 }
42474209 return false;
4248 } else {
4249 return child_ty.comptimeOnly(mod);
4250 }
4251 },
4210 },
42524211
4253 .optional => {
4254 return ty.optionalChild(mod).comptimeOnly(mod);
4255 },
4212 .@"struct" => {
4213 const struct_obj = ty.castTag(.@"struct").?.data;
4214 switch (struct_obj.requires_comptime) {
4215 .wip, .unknown => {
4216 // Return false to avoid incorrect dependency loops.
4217 // This will be handled correctly once merged with
4218 // `Sema.typeRequiresComptime`.
4219 return false;
4220 },
4221 .no => return false,
4222 .yes => return true,
4223 }
4224 },
42564225
4257 .tuple, .anon_struct => {
4258 const tuple = ty.tupleFields();
4259 for (tuple.types, 0..) |field_ty, i| {
4260 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;
4261 if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true;
4262 }
4263 return false;
4264 },
4226 .@"union", .union_safety_tagged, .union_tagged => {
4227 const union_obj = ty.cast(Type.Payload.Union).?.data;
4228 switch (union_obj.requires_comptime) {
4229 .wip, .unknown => {
4230 // Return false to avoid incorrect dependency loops.
4231 // This will be handled correctly once merged with
4232 // `Sema.typeRequiresComptime`.
4233 return false;
4234 },
4235 .no => return false,
4236 .yes => return true,
4237 }
4238 },
42654239
4266 .@"struct" => {
4267 const struct_obj = ty.castTag(.@"struct").?.data;
4268 switch (struct_obj.requires_comptime) {
4269 .wip, .unknown => {
4270 // Return false to avoid incorrect dependency loops.
4271 // This will be handled correctly once merged with
4272 // `Sema.typeRequiresComptime`.
4273 return false;
4274 },
4275 .no => return false,
4276 .yes => return true,
4277 }
4240 .error_union => return ty.errorUnionPayload().comptimeOnly(mod),
4241 .anyframe_T => {
4242 const child_ty = ty.castTag(.anyframe_T).?.data;
4243 return child_ty.comptimeOnly(mod);
4244 },
4245 .enum_numbered => {
4246 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
4247 return tag_ty.comptimeOnly(mod);
4248 },
4249 .enum_full, .enum_nonexhaustive => {
4250 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
4251 return tag_ty.comptimeOnly(mod);
4252 },
42784253 },
4279
4280 .@"union", .union_safety_tagged, .union_tagged => {
4281 const union_obj = ty.cast(Type.Payload.Union).?.data;
4282 switch (union_obj.requires_comptime) {
4283 .wip, .unknown => {
4284 // Return false to avoid incorrect dependency loops.
4285 // This will be handled correctly once merged with
4286 // `Sema.typeRequiresComptime`.
4254 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4255 .int_type => false,
4256 .ptr_type => |ptr_type| {
4257 const child_ty = ptr_type.elem_type.toType();
4258 if (child_ty.zigTypeTag(mod) == .Fn) {
42874259 return false;
4288 },
4289 .no => return false,
4290 .yes => return true,
4291 }
4292 },
4260 } else {
4261 return child_ty.comptimeOnly(mod);
4262 }
4263 },
4264 .array_type => |array_type| array_type.child.toType().comptimeOnly(mod),
4265 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),
4266 .opt_type => |child| child.toType().comptimeOnly(mod),
4267 .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod),
4268 .simple_type => |t| switch (t) {
4269 .f16,
4270 .f32,
4271 .f64,
4272 .f80,
4273 .f128,
4274 .usize,
4275 .isize,
4276 .c_char,
4277 .c_short,
4278 .c_ushort,
4279 .c_int,
4280 .c_uint,
4281 .c_long,
4282 .c_ulong,
4283 .c_longlong,
4284 .c_ulonglong,
4285 .c_longdouble,
4286 .anyopaque,
4287 .bool,
4288 .void,
4289 .anyerror,
4290 .@"anyframe",
4291 .noreturn,
4292 .generic_poison,
4293 .atomic_order,
4294 .atomic_rmw_op,
4295 .calling_convention,
4296 .address_space,
4297 .float_mode,
4298 .reduce_op,
4299 .call_modifier,
4300 .prefetch_options,
4301 .export_options,
4302 .extern_options,
4303 => false,
42934304
4294 .error_union => return ty.errorUnionPayload().comptimeOnly(mod),
4295 .anyframe_T => {
4296 const child_ty = ty.castTag(.anyframe_T).?.data;
4297 return child_ty.comptimeOnly(mod);
4298 },
4299 .enum_numbered => {
4300 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
4301 return tag_ty.comptimeOnly(mod);
4302 },
4303 .enum_full, .enum_nonexhaustive => {
4304 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
4305 return tag_ty.comptimeOnly(mod);
4305 .type,
4306 .comptime_int,
4307 .comptime_float,
4308 .null,
4309 .undefined,
4310 .enum_literal,
4311 .type_info,
4312 => true,
4313
4314 .var_args_param => unreachable,
4315 },
4316 .struct_type => @panic("TODO"),
4317 .union_type => @panic("TODO"),
4318 .simple_value => unreachable,
4319 .extern_func => unreachable,
4320 .int => unreachable,
4321 .enum_tag => unreachable, // it's a value, not a type
43064322 },
43074323 };
43084324 }
......@@ -4575,15 +4591,19 @@ pub const Type = struct {
45754591 }
45764592
45774593 pub fn structFields(ty: Type) Module.Struct.Fields {
4578 switch (ty.tag()) {
4579 .empty_struct, .empty_struct_literal => return .{},
4580 .@"struct" => {
4581 const struct_obj = ty.castTag(.@"struct").?.data;
4582 assert(struct_obj.haveFieldTypes());
4583 return struct_obj.fields;
4594 return switch (ty.ip_index) {
4595 .empty_struct_type => .{},
4596 .none => switch (ty.tag()) {
4597 .empty_struct => .{},
4598 .@"struct" => {
4599 const struct_obj = ty.castTag(.@"struct").?.data;
4600 assert(struct_obj.haveFieldTypes());
4601 return struct_obj.fields;
4602 },
4603 else => unreachable,
45844604 },
45854605 else => unreachable,
4586 }
4606 };
45874607 }
45884608
45894609 pub fn structFieldName(ty: Type, field_index: usize) []const u8 {
......@@ -4599,17 +4619,21 @@ pub const Type = struct {
45994619 }
46004620
46014621 pub fn structFieldCount(ty: Type) usize {
4602 switch (ty.tag()) {
4603 .@"struct" => {
4604 const struct_obj = ty.castTag(.@"struct").?.data;
4605 assert(struct_obj.haveFieldTypes());
4606 return struct_obj.fields.count();
4622 return switch (ty.ip_index) {
4623 .empty_struct_type => 0,
4624 .none => switch (ty.tag()) {
4625 .@"struct" => {
4626 const struct_obj = ty.castTag(.@"struct").?.data;
4627 assert(struct_obj.haveFieldTypes());
4628 return struct_obj.fields.count();
4629 },
4630 .empty_struct => 0,
4631 .tuple => ty.castTag(.tuple).?.data.types.len,
4632 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
4633 else => unreachable,
46074634 },
4608 .empty_struct, .empty_struct_literal => return 0,
4609 .tuple => return ty.castTag(.tuple).?.data.types.len,
4610 .anon_struct => return ty.castTag(.anon_struct).?.data.types.len,
46114635 else => unreachable,
4612 }
4636 };
46134637 }
46144638
46154639 /// Supports structs and unions.
......@@ -4927,10 +4951,6 @@ pub const Type = struct {
49274951 return ty.ip_index == .generic_poison_type;
49284952 }
49294953
4930 pub fn isVarArgsParam(ty: Type) bool {
4931 return ty.ip_index == .none and ty.tag() == .var_args_param;
4932 }
4933
49344954 /// This enum does not directly correspond to `std.builtin.TypeId` because
49354955 /// it has extra enum tags in it, as a way of using less memory. For example,
49364956 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
......@@ -4938,8 +4958,6 @@ pub const Type = struct {
49384958 /// with different enum tags, because the the former requires more payload data than the latter.
49394959 /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.
49404960 pub const Tag = enum(usize) {
4941 /// Same as `empty_struct` except it has an empty namespace.
4942 empty_struct_literal,
49434961 /// This is a special value that tracks a set of types that have been stored
49444962 /// to an inferred allocation. It does not support most of the normal type queries.
49454963 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
......@@ -4982,7 +5000,6 @@ pub const Type = struct {
49825000 return switch (t) {
49835001 .inferred_alloc_const,
49845002 .inferred_alloc_mut,
4985 .empty_struct_literal,
49865003 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
49875004
49885005 .optional,
......@@ -5038,33 +5055,36 @@ pub const Type = struct {
50385055
50395056 pub fn isTuple(ty: Type) bool {
50405057 return switch (ty.ip_index) {
5058 .empty_struct_type => true,
50415059 .none => switch (ty.tag()) {
5042 .tuple, .empty_struct_literal => true,
5060 .tuple => true,
50435061 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
50445062 else => false,
50455063 },
5046 else => false, // TODO
5064 else => false, // TODO struct
50475065 };
50485066 }
50495067
50505068 pub fn isAnonStruct(ty: Type) bool {
50515069 return switch (ty.ip_index) {
5070 .empty_struct_type => true,
50525071 .none => switch (ty.tag()) {
5053 .anon_struct, .empty_struct_literal => true,
5072 .anon_struct => true,
50545073 else => false,
50555074 },
5056 else => false, // TODO
5075 else => false, // TODO struct
50575076 };
50585077 }
50595078
50605079 pub fn isTupleOrAnonStruct(ty: Type) bool {
50615080 return switch (ty.ip_index) {
5081 .empty_struct_type => true,
50625082 .none => switch (ty.tag()) {
5063 .tuple, .empty_struct_literal, .anon_struct => true,
5083 .tuple, .anon_struct => true,
50645084 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
50655085 else => false,
50665086 },
5067 else => false, // TODO
5087 else => false, // TODO struct
50685088 };
50695089 }
50705090
......@@ -5072,7 +5092,7 @@ pub const Type = struct {
50725092 return switch (ty.ip_index) {
50735093 .empty_struct => true,
50745094 .none => switch (ty.tag()) {
5075 .tuple, .empty_struct_literal => true,
5095 .tuple => true,
50765096 else => false,
50775097 },
50785098 else => false, // TODO
......@@ -5083,7 +5103,7 @@ pub const Type = struct {
50835103 return switch (ty.ip_index) {
50845104 .empty_struct => true,
50855105 .none => switch (ty.tag()) {
5086 .tuple, .empty_struct_literal, .anon_struct => true,
5106 .tuple, .anon_struct => true,
50875107 else => false,
50885108 },
50895109 else => false,
......@@ -5100,7 +5120,6 @@ pub const Type = struct {
51005120 .types = ty.castTag(.anon_struct).?.data.types,
51015121 .values = ty.castTag(.anon_struct).?.data.values,
51025122 },
5103 .empty_struct_literal => .{ .types = &.{}, .values = &.{} },
51045123 else => unreachable,
51055124 },
51065125 else => unreachable,
......@@ -5387,6 +5406,7 @@ pub const Type = struct {
53875406 .ip_index = .const_slice_u8_sentinel_0_type,
53885407 .legacy = undefined,
53895408 };
5409 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type, .legacy = undefined };
53905410
53915411 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type, .legacy = undefined };
53925412
src/value.zig+13-19
......@@ -36,7 +36,6 @@ pub const Value = struct {
3636 /// The only possible value for a particular type, which is stored externally.
3737 the_only_possible_value,
3838
39 empty_struct_value,
4039 empty_array, // See last_no_payload_tag below.
4140 // After this, the tag requires a payload.
4241
......@@ -124,7 +123,6 @@ pub const Value = struct {
124123 pub fn Type(comptime t: Tag) type {
125124 return switch (t) {
126125 .the_only_possible_value,
127 .empty_struct_value,
128126 .empty_array,
129127 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
130128
......@@ -269,7 +267,6 @@ pub const Value = struct {
269267 } else switch (self.legacy.ptr_otherwise.tag) {
270268 .the_only_possible_value,
271269 .empty_array,
272 .empty_struct_value,
273270 => unreachable,
274271
275272 .ty, .lazy_align, .lazy_size => {
......@@ -488,7 +485,6 @@ pub const Value = struct {
488485 }
489486 var val = start_val;
490487 while (true) switch (val.tag()) {
491 .empty_struct_value => return out_stream.writeAll("struct {}{}"),
492488 .aggregate => {
493489 return out_stream.writeAll("(aggregate)");
494490 },
......@@ -1914,7 +1910,7 @@ pub const Value = struct {
19141910 const a_tag = a.tag();
19151911 const b_tag = b.tag();
19161912 if (a_tag == b_tag) switch (a_tag) {
1917 .the_only_possible_value, .empty_struct_value => return true,
1913 .the_only_possible_value => return true,
19181914 .enum_literal => {
19191915 const a_name = a.castTag(.enum_literal).?.data;
19201916 const b_name = b.castTag(.enum_literal).?.data;
......@@ -2106,7 +2102,6 @@ pub const Value = struct {
21062102 },
21072103 .Struct => {
21082104 // A struct can be represented with one of:
2109 // .empty_struct_value,
21102105 // .the_one_possible_value,
21112106 // .aggregate,
21122107 // Note that we already checked above for matching tags, e.g. both .aggregate.
......@@ -2254,7 +2249,6 @@ pub const Value = struct {
22542249 },
22552250 .Struct => {
22562251 switch (val.tag()) {
2257 .empty_struct_value => {},
22582252 .aggregate => {
22592253 const field_values = val.castTag(.aggregate).?.data;
22602254 for (field_values, 0..) |field_val, i| {
......@@ -2587,7 +2581,6 @@ pub const Value = struct {
25872581 .none => switch (val.tag()) {
25882582 // This is the case of accessing an element of an undef array.
25892583 .empty_array => unreachable, // out of bounds array index
2590 .empty_struct_value => unreachable, // out of bounds array index
25912584
25922585 .empty_array_sentinel => {
25932586 assert(index == 0); // The only valid index for an empty array with sentinel.
......@@ -2749,6 +2742,17 @@ pub const Value = struct {
27492742 pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {
27502743 switch (val.ip_index) {
27512744 .undef => return Value.undef,
2745 .empty_struct => {
2746 if (ty.isSimpleTupleOrAnonStruct()) {
2747 const tuple = ty.tupleFields();
2748 return tuple.values[index];
2749 }
2750 if (try ty.structFieldValueComptime(mod, index)) |some| {
2751 return some;
2752 }
2753 unreachable;
2754 },
2755
27522756 .none => switch (val.tag()) {
27532757 .aggregate => {
27542758 const field_values = val.castTag(.aggregate).?.data;
......@@ -2762,17 +2766,6 @@ pub const Value = struct {
27622766
27632767 .the_only_possible_value => return (try ty.onePossibleValue(mod)).?,
27642768
2765 .empty_struct_value => {
2766 if (ty.isSimpleTupleOrAnonStruct()) {
2767 const tuple = ty.tupleFields();
2768 return tuple.values[index];
2769 }
2770 if (try ty.structFieldValueComptime(mod, index)) |some| {
2771 return some;
2772 }
2773 unreachable;
2774 },
2775
27762769 else => unreachable,
27772770 },
27782771 else => unreachable,
......@@ -5189,6 +5182,7 @@ pub const Value = struct {
51895182
51905183 pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };
51915184 pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined };
5185 pub const empty_struct: Value = .{ .ip_index = .empty_struct, .legacy = undefined };
51925186
51935187 pub fn makeBool(x: bool) Value {
51945188 return if (x) Value.true else Value.false;