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(...@@ -12615,7 +12615,7 @@ fn analyzeTupleCat(
12615 const dest_fields = lhs_len + rhs_len;12615 const dest_fields = lhs_len + rhs_len;
1261612616
12617 if (dest_fields == 0) {12617 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);
12619 }12619 }
12620 if (lhs_len == 0) {12620 if (lhs_len == 0) {
12621 return rhs;12621 return rhs;
...@@ -12943,7 +12943,7 @@ fn analyzeTupleMul(...@@ -12943,7 +12943,7 @@ fn analyzeTupleMul(
12943 return sema.fail(block, rhs_src, "operation results in overflow", .{});12943 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1294412944
12945 if (final_len_u64 == 0) {12945 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);
12947 }12947 }
12948 const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);12948 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...@@ -21860,7 +21860,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
21860 const args = try sema.resolveInst(extra.args);21860 const args = try sema.resolveInst(extra.args);
2186121861
21862 const args_ty = sema.typeOf(args);21862 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) {
21864 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});21864 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});
21865 }21865 }
2186621866
...@@ -24780,37 +24780,41 @@ fn structFieldVal(...@@ -24780,37 +24780,41 @@ fn structFieldVal(
24780 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);24780 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
2478124781
24782 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);24782 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24783 switch (struct_ty.tag()) {24783 switch (struct_ty.ip_index) {
24784 .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),24784 .empty_struct_type => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24785 .anon_struct => {24785 .none => switch (struct_ty.tag()) {
24786 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);24786 .tuple => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24787 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);24787 .anon_struct => {
24788 },24788 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24789 .@"struct" => {24789 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24790 const struct_obj = struct_ty.castTag(.@"struct").?.data;24790 },
24791 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);24791 .@"struct" => {
2479224792 const struct_obj = struct_ty.castTag(.@"struct").?.data;
24793 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse24793 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
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];
2479724794
24798 if (field.is_comptime) {24795 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
24799 return sema.addConstant(field.ty, field.default_val);24796 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
24800 }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| {24800 if (field.is_comptime) {
24803 if (struct_val.isUndef()) return sema.addConstUndef(field.ty);24801 return sema.addConstant(field.ty, field.default_val);
24804 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
24805 return sema.addConstant(field.ty, opv);
24806 }24802 }
2480724803
24808 const field_values = struct_val.castTag(.aggregate).?.data;24804 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {
24809 return sema.addConstant(field.ty, field_values[field_index]);24805 if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
24810 }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);24814 try sema.requireRuntimeBlock(block, src, null);
24813 return block.addStructFieldVal(struct_byval, field_index, field.ty);24815 return block.addStructFieldVal(struct_byval, field_index, field.ty);
24816 },
24817 else => unreachable,
24814 },24818 },
24815 else => unreachable,24819 else => unreachable,
24816 }24820 }
...@@ -27848,6 +27852,19 @@ fn beginComptimePtrMutation(...@@ -27848,6 +27852,19 @@ fn beginComptimePtrMutation(
27848 else => unreachable,27852 else => unreachable,
27849 }27853 }
27850 },27854 },
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 },
27851 .none => switch (val_ptr.tag()) {27868 .none => switch (val_ptr.tag()) {
27852 .aggregate => return beginComptimePtrMutationInner(27869 .aggregate => return beginComptimePtrMutationInner(
27853 sema,27870 sema,
...@@ -27901,20 +27918,6 @@ fn beginComptimePtrMutation(...@@ -27901,20 +27918,6 @@ fn beginComptimePtrMutation(
27901 else => unreachable,27918 else => unreachable,
27902 },27919 },
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
27918 else => unreachable,27921 else => unreachable,
27919 },27922 },
27920 else => unreachable,27923 else => unreachable,
...@@ -31502,174 +31505,174 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31502,174 +31505,174 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
31502pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {31505pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31503 const mod = sema.mod;31506 const mod = sema.mod;
3150431507
31505 if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {31508 return switch (ty.ip_index) {
31506 .int_type => false,31509 .empty_struct_type => false,
31507 .ptr_type => |ptr_type| {31510 .none => switch (ty.tag()) {
31508 const child_ty = ptr_type.elem_type.toType();31511 .empty_struct,
31509 if (child_ty.zigTypeTag(mod) == .Fn) {31512 .error_set,
31510 return child_ty.fnInfo().is_generic;31513 .error_set_single,
31511 } else {31514 .error_set_inferred,
31512 return sema.resolveTypeRequiresComptime(child_ty);31515 .error_set_merged,
31513 }31516 .@"opaque",
31514 },31517 .enum_simple,
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,
31554 => false,31518 => false,
3155531519
31556 .type,31520 .function => true,
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,
3158531521
31586 .function => true,31522 .inferred_alloc_mut => unreachable,
31523 .inferred_alloc_const => unreachable,
3158731524
31588 .inferred_alloc_mut => unreachable,31525 .array,
31589 .inferred_alloc_const => unreachable,31526 .array_sentinel,
31527 => return sema.resolveTypeRequiresComptime(ty.childType(mod)),
3159031528
31591 .array,31529 .pointer => {
31592 .array_sentinel,31530 const child_ty = ty.childType(mod);
31593 => return sema.resolveTypeRequiresComptime(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 => {31538 .optional => {
31596 const child_ty = ty.childType(mod);31539 return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));
31597 if (child_ty.zigTypeTag(mod) == .Fn) {31540 },
31598 return child_ty.fnInfo().is_generic;
31599 } else {
31600 return sema.resolveTypeRequiresComptime(child_ty);
31601 }
31602 },
3160331541
31604 .optional => {31542 .tuple, .anon_struct => {
31605 return sema.resolveTypeRequiresComptime(ty.optionalChild(mod));31543 const tuple = ty.tupleFields();
31606 },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 => {31553 .@"struct" => {
31609 const tuple = ty.tupleFields();31554 const struct_obj = ty.castTag(.@"struct").?.data;
31610 for (tuple.types, 0..) |field_ty, i| {31555 switch (struct_obj.requires_comptime) {
31611 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;31556 .no, .wip => return false,
31612 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {31557 .yes => return true,
31613 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 },
31614 }31571 }
31615 }31572 },
31616 return false;
31617 },
3161831573
31619 .@"struct" => {31574 .@"union", .union_safety_tagged, .union_tagged => {
31620 const struct_obj = ty.castTag(.@"struct").?.data;31575 const union_obj = ty.cast(Type.Payload.Union).?.data;
31621 switch (struct_obj.requires_comptime) {31576 switch (union_obj.requires_comptime) {
31622 .no, .wip => return false,31577 .no, .wip => return false,
31623 .yes => return true,31578 .yes => return true,
31624 .unknown => {31579 .unknown => {
31625 var requires_comptime = false;31580 var requires_comptime = false;
31626 struct_obj.requires_comptime = .wip;31581 union_obj.requires_comptime = .wip;
31627 for (struct_obj.fields.values()) |field| {31582 for (union_obj.fields.values()) |field| {
31628 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;31583 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31629 }31584 }
31630 if (requires_comptime) {31585 if (requires_comptime) {
31631 struct_obj.requires_comptime = .yes;31586 union_obj.requires_comptime = .yes;
31632 } else {31587 } else {
31633 struct_obj.requires_comptime = .no;31588 union_obj.requires_comptime = .no;
31634 }31589 }
31635 return requires_comptime;31590 return requires_comptime;
31636 },31591 },
31637 }31592 }
31638 },31593 },
3163931594
31640 .@"union", .union_safety_tagged, .union_tagged => {31595 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
31641 const union_obj = ty.cast(Type.Payload.Union).?.data;31596 .anyframe_T => {
31642 switch (union_obj.requires_comptime) {31597 const child_ty = ty.castTag(.anyframe_T).?.data;
31643 .no, .wip => return false,31598 return sema.resolveTypeRequiresComptime(child_ty);
31644 .yes => return true,31599 },
31645 .unknown => {31600 .enum_numbered => {
31646 var requires_comptime = false;31601 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
31647 union_obj.requires_comptime = .wip;31602 return sema.resolveTypeRequiresComptime(tag_ty);
31648 for (union_obj.fields.values()) |field| {31603 },
31649 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;31604 .enum_full, .enum_nonexhaustive => {
31650 }31605 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
31651 if (requires_comptime) {31606 return sema.resolveTypeRequiresComptime(tag_ty);
31652 union_obj.requires_comptime = .yes;31607 },
31653 } else {
31654 union_obj.requires_comptime = .no;
31655 }
31656 return requires_comptime;
31657 },
31658 }
31659 },31608 },
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()),31661 .type,
31662 .anyframe_T => {31662 .comptime_int,
31663 const child_ty = ty.castTag(.anyframe_T).?.data;31663 .comptime_float,
31664 return sema.resolveTypeRequiresComptime(child_ty);31664 .null,
31665 },31665 .undefined,
31666 .enum_numbered => {31666 .enum_literal,
31667 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;31667 .type_info,
31668 return sema.resolveTypeRequiresComptime(tag_ty);31668 => true,
31669 },31669 },
31670 .enum_full, .enum_nonexhaustive => {31670 .struct_type => @panic("TODO"),
31671 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;31671 .union_type => @panic("TODO"),
31672 return sema.resolveTypeRequiresComptime(tag_ty);31672 .simple_value => unreachable,
31673 .extern_func => unreachable,
31674 .int => unreachable,
31675 .enum_tag => unreachable, // it's a value, not a type
31673 },31676 },
31674 };31677 };
31675}31678}
...@@ -32957,237 +32960,240 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -32957,237 +32960,240 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
32957pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {32960pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
32958 const mod = sema.mod;32961 const mod = sema.mod;
3295932962
32960 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {32963 switch (ty.ip_index) {
32961 .int_type => |int_type| {32964 .empty_struct_type => return Value.empty_struct,
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,
3302832965
33029 .void => return Value.void,32966 .none => switch (ty.tag()) {
33030 .noreturn => return Value.@"unreachable",32967 .error_set_single,
33031 .null => return Value.null,32968 .error_set,
33032 .undefined => return Value.undef,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,32979 .optional => {
33035 .var_args_param => unreachable,32980 const child_ty = ty.optionalChild(mod);
33036 },32981 if (child_ty.isNoReturn()) {
33037 .struct_type => @panic("TODO"),32982 return Value.null;
33038 .union_type => @panic("TODO"),32983 } else {
33039 .simple_value => unreachable,32984 return null;
33040 .extern_func => unreachable,32985 }
33041 .int => unreachable,32986 },
33042 .enum_tag => unreachable, // it's a value, not a type
33043 };
3304432987
33045 switch (ty.tag()) {32988 .@"struct" => {
33046 .error_set_single,32989 const resolved_ty = try sema.resolveTypeFields(ty);
33047 .error_set,32990 const s = resolved_ty.castTag(.@"struct").?.data;
33048 .error_set_merged,32991 for (s.fields.values(), 0..) |field, i| {
33049 .error_union,32992 if (field.is_comptime) continue;
33050 .function,32993 if (field.ty.eql(resolved_ty, sema.mod)) {
33051 .array_sentinel,32994 const msg = try Module.ErrorMsg.create(
33052 .error_set_inferred,32995 sema.gpa,
33053 .@"opaque",32996 s.srcLoc(sema.mod),
33054 .anyframe_T,32997 "struct '{}' depends on itself",
33055 .pointer,32998 .{ty.fmt(sema.mod)},
33056 => return null,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 => {33010 .tuple, .anon_struct => {
33059 const child_ty = ty.optionalChild(mod);33011 const tuple = ty.tupleFields();
33060 if (child_ty.isNoReturn()) {33012 for (tuple.values, 0..) |val, i| {
33061 return Value.null;33013 const is_comptime = val.ip_index != .unreachable_value;
33062 } else {33014 if (is_comptime) continue;
33063 return null;33015 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;
33064 }33016 return null;
33065 },33017 }
33018 return Value.empty_struct;
33019 },
3306633020
33067 .@"struct" => {33021 .enum_numbered => {
33068 const resolved_ty = try sema.resolveTypeFields(ty);33022 const resolved_ty = try sema.resolveTypeFields(ty);
33069 const s = resolved_ty.castTag(.@"struct").?.data;33023 const enum_obj = resolved_ty.castTag(.enum_numbered).?.data;
33070 for (s.fields.values(), 0..) |field, i| {33024 // An explicit tag type is always provided for enum_numbered.
33071 if (field.is_comptime) continue;33025 if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) {
33072 if (field.ty.eql(resolved_ty, sema.mod)) {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)) {
33073 const msg = try Module.ErrorMsg.create(33080 const msg = try Module.ErrorMsg.create(
33074 sema.gpa,33081 sema.gpa,
33075 s.srcLoc(sema.mod),33082 union_obj.srcLoc(sema.mod),
33076 "struct '{}' depends on itself",33083 "union '{}' depends on itself",
33077 .{ty.fmt(sema.mod)},33084 .{ty.fmt(sema.mod)},
33078 );33085 );
33079 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});33086 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
33080 return sema.failWithOwnedErrorMsg(msg);33087 return sema.failWithOwnedErrorMsg(msg);
33081 }33088 }
33082 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {33089 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
33083 return null;33090 return null;
33084 }33091 // TODO make this not allocate.
33085 }33092 return try Value.Tag.@"union".create(sema.arena, .{
33086 return Value.initTag(.empty_struct_value);33093 .tag = tag_val,
33087 },33094 .val = val_val,
33095 });
33096 },
33097
33098 .empty_struct => return Value.empty_struct,
3308833099
33089 .tuple, .anon_struct => {33100 .array => {
33090 const tuple = ty.tupleFields();33101 if (ty.arrayLen(mod) == 0)
33091 for (tuple.values, 0..) |val, i| {33102 return Value.initTag(.empty_array);
33092 const is_comptime = val.ip_index != .unreachable_value;33103 if ((try sema.typeHasOnePossibleValue(ty.childType(mod))) != null) {
33093 if (is_comptime) continue;33104 return Value.initTag(.the_only_possible_value);
33094 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;33105 }
33095 return null;33106 return null;
33096 }33107 },
33097 return Value.initTag(.empty_struct_value);33108
33109 .inferred_alloc_const => unreachable,
33110 .inferred_alloc_mut => unreachable,
33098 },33111 },
3309933112
33100 .enum_numbered => {33113 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
33101 const resolved_ty = try sema.resolveTypeFields(ty);33114 .int_type => |int_type| {
33102 const enum_obj = resolved_ty.castTag(.enum_numbered).?.data;33115 if (int_type.bits == 0) {
33103 // An explicit tag type is always provided for enum_numbered.33116 return try mod.intValue(ty, 0);
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
33110 } else {33117 } 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);
33112 }33127 }
33113 } else {
33114 return null;33128 return null;
33115 }33129 },
33116 },33130 .vector_type => |vector_type| {
33117 .enum_full => {33131 if (vector_type.len == 0) return Value.initTag(.empty_array);
33118 const resolved_ty = try sema.resolveTypeFields(ty);33132 if (try sema.typeHasOnePossibleValue(vector_type.child.toType())) |v| return v;
33119 const enum_obj = resolved_ty.castTag(.enum_full).?.data;
33120 if (!(try sema.typeHasRuntimeBits(enum_obj.tag_ty))) {
33121 return null;33133 return null;
33122 }33134 },
33123 switch (enum_obj.fields.count()) {33135 .opt_type => |child| {
33124 0 => return Value.@"unreachable",33136 if (child.toType().isNoReturn()) {
33125 1 => if (enum_obj.values.count() == 0) {33137 return Value.null;
33126 return try mod.intValue(ty, 0); // auto-numbered
33127 } else {33138 } else {
33128 return enum_obj.values.keys()[0];33139 return null;
33129 },33140 }
33130 else => return null,33141 },
33131 }33142 .error_union_type => return null,
33132 },33143 .simple_type => |t| switch (t) {
33133 .enum_simple => {33144 .f16,
33134 const resolved_ty = try sema.resolveTypeFields(ty);33145 .f32,
33135 const enum_simple = resolved_ty.castTag(.enum_simple).?.data;33146 .f64,
33136 switch (enum_simple.fields.count()) {33147 .f80,
33137 0 => return Value.@"unreachable",33148 .f128,
33138 1 => return try mod.intValue(ty, 0),33149 .usize,
33139 else => return null,33150 .isize,
33140 }33151 .c_char,
33141 },33152 .c_short,
33142 .enum_nonexhaustive => {33153 .c_ushort,
33143 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;33154 .c_int,
33144 if (tag_ty.zigTypeTag(mod) != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) {33155 .c_uint,
33145 return try mod.intValue(ty, 0);33156 .c_long,
33146 } else {33157 .c_ulong,
33147 return null;33158 .c_longlong,
33148 }33159 .c_ulonglong,
33149 },33160 .c_longdouble,
33150 .@"union", .union_safety_tagged, .union_tagged => {33161 .anyopaque,
33151 const resolved_ty = try sema.resolveTypeFields(ty);33162 .bool,
33152 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;33163 .type,
33153 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse33164 .anyerror,
33154 return null;33165 .comptime_int,
33155 const fields = union_obj.fields.values();33166 .comptime_float,
33156 if (fields.len == 0) return Value.@"unreachable";33167 .@"anyframe",
33157 const only_field = fields[0];33168 .enum_literal,
33158 if (only_field.ty.eql(resolved_ty, sema.mod)) {33169 .atomic_order,
33159 const msg = try Module.ErrorMsg.create(33170 .atomic_rmw_op,
33160 sema.gpa,33171 .calling_convention,
33161 union_obj.srcLoc(sema.mod),33172 .address_space,
33162 "union '{}' depends on itself",33173 .float_mode,
33163 .{ty.fmt(sema.mod)},33174 .reduce_op,
33164 );33175 .call_modifier,
33165 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});33176 .prefetch_options,
33166 return sema.failWithOwnedErrorMsg(msg);33177 .export_options,
33167 }33178 .extern_options,
33168 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse33179 .type_info,
33169 return null;33180 => 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 },
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 => {33187 .generic_poison => return error.GenericPoison,
33181 if (ty.arrayLen(mod) == 0)33188 .var_args_param => unreachable,
33182 return Value.initTag(.empty_array);33189 },
33183 if ((try sema.typeHasOnePossibleValue(ty.childType(mod))) != null) {33190 .struct_type => @panic("TODO"),
33184 return Value.initTag(.the_only_possible_value);33191 .union_type => @panic("TODO"),
33185 }33192 .simple_value => unreachable,
33186 return null;33193 .extern_func => unreachable,
33194 .int => unreachable,
33195 .enum_tag => unreachable, // it's a value, not a type
33187 },33196 },
33188
33189 .inferred_alloc_const => unreachable,
33190 .inferred_alloc_mut => unreachable,
33191 }33197 }
33192}33198}
3319333199
...@@ -33567,8 +33573,116 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {...@@ -33567,8 +33573,116 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
33567/// elsewhere in value.zig33573/// elsewhere in value.zig
33568pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {33574pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33569 const mod = sema.mod;33575 const mod = sema.mod;
33570 if (ty.ip_index != .none) {33576 return switch (ty.ip_index) {
33571 switch (mod.intern_pool.indexToKey(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)) {
33572 .int_type => return false,33686 .int_type => return false,
33573 .ptr_type => |ptr_type| {33687 .ptr_type => |ptr_type| {
33574 const child_ty = ptr_type.elem_type.toType();33688 const child_ty = ptr_type.elem_type.toType();
...@@ -33638,113 +33752,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33638,113 +33752,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33638 .extern_func => unreachable,33752 .extern_func => unreachable,
33639 .int => unreachable,33753 .int => unreachable,
33640 .enum_tag => unreachable, // it's a value, not a type33754 .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);
33748 },33755 },
33749 };33756 };
33750}33757}
src/TypedValue.zig+69-60
...@@ -80,67 +80,9 @@ pub fn print(...@@ -80,67 +80,9 @@ pub fn print(
80 return writer.writeAll("(variable)");80 return writer.writeAll("(variable)");
8181
82 while (true) switch (val.ip_index) {82 while (true) switch (val.ip_index) {
83 .empty_struct => return printAggregate(ty, val, writer, level, mod),
83 .none => switch (val.tag()) {84 .none => switch (val.tag()) {
84 .empty_struct_value, .aggregate => {85 .aggregate => return printAggregate(ty, val, writer, level, mod),
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 },
144 .@"union" => {86 .@"union" => {
145 if (level == 0) {87 if (level == 0) {
146 return writer.writeAll(".{ ... }");88 return writer.writeAll(".{ ... }");
...@@ -426,3 +368,70 @@ pub fn print(...@@ -426,3 +368,70 @@ pub fn print(
426 },368 },
427 };369 };
428}370}
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 {...@@ -1127,8 +1127,19 @@ pub const DeclGen = struct {
1127 try writer.writeByte('}');1127 try writer.writeByte('}');
1128 return;1128 return;
1129 },1129 },
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 },
1130 .none => switch (val.tag()) {1141 .none => switch (val.tag()) {
1131 .empty_struct_value, .empty_array => {1142 .empty_array => {
1132 const ai = ty.arrayInfo(mod);1143 const ai = ty.arrayInfo(mod);
1133 try writer.writeByte('{');1144 try writer.writeByte('{');
1134 if (ai.sentinel) |s| {1145 if (ai.sentinel) |s| {
src/type.zig+1464-1444
...@@ -34,8 +34,51 @@ pub const Type = struct {...@@ -34,8 +34,51 @@ pub const Type = struct {
34 }34 }
3535
36 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {36 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
37 if (ty.ip_index != .none) {37 switch (ty.ip_index) {
38 switch (mod.intern_pool.indexToKey(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)) {
39 .int_type => return .Int,82 .int_type => return .Int,
40 .ptr_type => return .Pointer,83 .ptr_type => return .Pointer,
41 .array_type => return .Array,84 .array_type => return .Array,
...@@ -104,51 +147,7 @@ pub const Type = struct {...@@ -104,51 +147,7 @@ pub const Type = struct {
104 .enum_tag,147 .enum_tag,
105 .simple_value,148 .simple_value,
106 => unreachable, // it's a value, not a type149 => unreachable, // it's a value, not a type
107 }150 },
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,
152 }151 }
153 }152 }
154153
...@@ -517,7 +516,7 @@ pub const Type = struct {...@@ -517,7 +516,7 @@ pub const Type = struct {
517 const b_struct_obj = (b.castTag(.@"struct") orelse return false).data;516 const b_struct_obj = (b.castTag(.@"struct") orelse return false).data;
518 return a_struct_obj == b_struct_obj;517 return a_struct_obj == b_struct_obj;
519 },518 },
520 .tuple, .empty_struct_literal => {519 .tuple => {
521 if (!b.isSimpleTuple()) return false;520 if (!b.isSimpleTuple()) return false;
522521
523 const a_tuple = a.tupleFields();522 const a_tuple = a.tupleFields();
...@@ -741,7 +740,7 @@ pub const Type = struct {...@@ -741,7 +740,7 @@ pub const Type = struct {
741 const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data;740 const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data;
742 std.hash.autoHash(hasher, struct_obj);741 std.hash.autoHash(hasher, struct_obj);
743 },742 },
744 .tuple, .empty_struct_literal => {743 .tuple => {
745 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);744 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
746745
747 const tuple = ty.tupleFields();746 const tuple = ty.tupleFields();
...@@ -837,7 +836,6 @@ pub const Type = struct {...@@ -837,7 +836,6 @@ pub const Type = struct {
837 } else switch (self.legacy.ptr_otherwise.tag) {836 } else switch (self.legacy.ptr_otherwise.tag) {
838 .inferred_alloc_const,837 .inferred_alloc_const,
839 .inferred_alloc_mut,838 .inferred_alloc_mut,
840 .empty_struct_literal,
841 => unreachable,839 => unreachable,
842840
843 .optional,841 .optional,
...@@ -1047,7 +1045,7 @@ pub const Type = struct {...@@ -1047,7 +1045,7 @@ pub const Type = struct {
1047 while (true) {1045 while (true) {
1048 const t = ty.tag();1046 const t = ty.tag();
1049 switch (t) {1047 switch (t) {
1050 .empty_struct, .empty_struct_literal => return writer.writeAll("struct {}"),1048 .empty_struct => return writer.writeAll("struct {}"),
10511049
1052 .@"struct" => {1050 .@"struct" => {
1053 const struct_obj = ty.castTag(.@"struct").?.data;1051 const struct_obj = ty.castTag(.@"struct").?.data;
...@@ -1266,327 +1264,328 @@ pub const Type = struct {...@@ -1266,327 +1264,328 @@ pub const Type = struct {
12661264
1267 /// Prints a name suitable for `@typeName`.1265 /// Prints a name suitable for `@typeName`.
1268 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {1266 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)) {1267 switch (ty.ip_index) {
1270 .int_type => |int_type| {1268 .empty_struct_type => try writer.writeAll("@TypeOf(.{})"),
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,
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 => {1274 .empty_struct => {
1364 const namespace = ty.castTag(.empty_struct).?.data;1275 const namespace = ty.castTag(.empty_struct).?.data;
1365 try namespace.renderFullyQualifiedName(mod, "", writer);1276 try namespace.renderFullyQualifiedName(mod, "", writer);
1366 },1277 },
13671278
1368 .@"struct" => {1279 .@"struct" => {
1369 const struct_obj = ty.castTag(.@"struct").?.data;1280 const struct_obj = ty.castTag(.@"struct").?.data;
1370 const decl = mod.declPtr(struct_obj.owner_decl);1281 const decl = mod.declPtr(struct_obj.owner_decl);
1371 try decl.renderFullyQualifiedName(mod, writer);1282 try decl.renderFullyQualifiedName(mod, writer);
1372 },1283 },
1373 .@"union", .union_safety_tagged, .union_tagged => {1284 .@"union", .union_safety_tagged, .union_tagged => {
1374 const union_obj = ty.cast(Payload.Union).?.data;1285 const union_obj = ty.cast(Payload.Union).?.data;
1375 const decl = mod.declPtr(union_obj.owner_decl);1286 const decl = mod.declPtr(union_obj.owner_decl);
1376 try decl.renderFullyQualifiedName(mod, writer);1287 try decl.renderFullyQualifiedName(mod, writer);
1377 },1288 },
1378 .enum_full, .enum_nonexhaustive => {1289 .enum_full, .enum_nonexhaustive => {
1379 const enum_full = ty.cast(Payload.EnumFull).?.data;1290 const enum_full = ty.cast(Payload.EnumFull).?.data;
1380 const decl = mod.declPtr(enum_full.owner_decl);1291 const decl = mod.declPtr(enum_full.owner_decl);
1381 try decl.renderFullyQualifiedName(mod, writer);1292 try decl.renderFullyQualifiedName(mod, writer);
1382 },1293 },
1383 .enum_simple => {1294 .enum_simple => {
1384 const enum_simple = ty.castTag(.enum_simple).?.data;1295 const enum_simple = ty.castTag(.enum_simple).?.data;
1385 const decl = mod.declPtr(enum_simple.owner_decl);1296 const decl = mod.declPtr(enum_simple.owner_decl);
1386 try decl.renderFullyQualifiedName(mod, writer);1297 try decl.renderFullyQualifiedName(mod, writer);
1387 },1298 },
1388 .enum_numbered => {1299 .enum_numbered => {
1389 const enum_numbered = ty.castTag(.enum_numbered).?.data;1300 const enum_numbered = ty.castTag(.enum_numbered).?.data;
1390 const decl = mod.declPtr(enum_numbered.owner_decl);1301 const decl = mod.declPtr(enum_numbered.owner_decl);
1391 try decl.renderFullyQualifiedName(mod, writer);1302 try decl.renderFullyQualifiedName(mod, writer);
1392 },1303 },
1393 .@"opaque" => {1304 .@"opaque" => {
1394 const opaque_obj = ty.cast(Payload.Opaque).?.data;1305 const opaque_obj = ty.cast(Payload.Opaque).?.data;
1395 const decl = mod.declPtr(opaque_obj.owner_decl);1306 const decl = mod.declPtr(opaque_obj.owner_decl);
1396 try decl.renderFullyQualifiedName(mod, writer);1307 try decl.renderFullyQualifiedName(mod, writer);
1397 },1308 },
13981309
1399 .error_set_inferred => {1310 .error_set_inferred => {
1400 const func = ty.castTag(.error_set_inferred).?.data.func;1311 const func = ty.castTag(.error_set_inferred).?.data.func;
14011312
1402 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");1313 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
1403 const owner_decl = mod.declPtr(func.owner_decl);1314 const owner_decl = mod.declPtr(func.owner_decl);
1404 try owner_decl.renderFullyQualifiedName(mod, writer);1315 try owner_decl.renderFullyQualifiedName(mod, writer);
1405 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");1316 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
1406 },1317 },
14071318
1408 .function => {1319 .function => {
1409 const fn_info = ty.fnInfo();1320 const fn_info = ty.fnInfo();
1410 if (fn_info.is_noinline) {1321 if (fn_info.is_noinline) {
1411 try writer.writeAll("noinline ");1322 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 ");
1418 }1323 }
1419 if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) {1324 try writer.writeAll("fn(");
1420 try writer.writeAll("noalias ");1325 for (fn_info.param_types, 0..) |param_ty, i| {
1421 };1326 if (i != 0) try writer.writeAll(", ");
1422 if (param_ty.isGenericPoison()) {1327 if (fn_info.paramIsComptime(i)) {
1423 try writer.writeAll("anytype");1328 try writer.writeAll("comptime ");
1424 } else {1329 }
1425 try print(param_ty, writer, mod);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 }
1426 }1338 }
1427 }1339 if (fn_info.is_var_args) {
1428 if (fn_info.is_var_args) {1340 if (fn_info.param_types.len != 0) {
1429 if (fn_info.param_types.len != 0) {1341 try writer.writeAll(", ");
1430 try writer.writeAll(", ");1342 }
1343 try writer.writeAll("...");
1431 }1344 }
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));
1441 try writer.writeAll(") ");1345 try writer.writeAll(") ");
1442 }1346 if (fn_info.alignment != 0) {
1443 if (fn_info.return_type.isGenericPoison()) {1347 try writer.print("align({d}) ", .{fn_info.alignment});
1444 try writer.writeAll("anytype");1348 }
1445 } else {1349 if (fn_info.cc != .Unspecified) {
1446 try print(fn_info.return_type, writer, mod);1350 try writer.writeAll("callconv(.");
1447 }1351 try writer.writeAll(@tagName(fn_info.cc));
1448 },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 => {1361 .error_union => {
1451 const error_union = ty.castTag(.error_union).?.data;1362 const error_union = ty.castTag(.error_union).?.data;
1452 try print(error_union.error_set, writer, mod);1363 try print(error_union.error_set, writer, mod);
1453 try writer.writeAll("!");1364 try writer.writeAll("!");
1454 try print(error_union.payload, writer, mod);1365 try print(error_union.payload, writer, mod);
1455 },1366 },
14561367
1457 .array => {1368 .array => {
1458 const payload = ty.castTag(.array).?.data;1369 const payload = ty.castTag(.array).?.data;
1459 try writer.print("[{d}]", .{payload.len});1370 try writer.print("[{d}]", .{payload.len});
1460 try print(payload.elem_type, writer, mod);1371 try print(payload.elem_type, writer, mod);
1461 },1372 },
1462 .array_sentinel => {1373 .array_sentinel => {
1463 const payload = ty.castTag(.array_sentinel).?.data;1374 const payload = ty.castTag(.array_sentinel).?.data;
1464 try writer.print("[{d}:{}]", .{1375 try writer.print("[{d}:{}]", .{
1465 payload.len,1376 payload.len,
1466 payload.sentinel.fmtValue(payload.elem_type, mod),1377 payload.sentinel.fmtValue(payload.elem_type, mod),
1467 });1378 });
1468 try print(payload.elem_type, writer, mod);1379 try print(payload.elem_type, writer, mod);
1469 },1380 },
1470 .tuple => {1381 .tuple => {
1471 const tuple = ty.castTag(.tuple).?.data;1382 const tuple = ty.castTag(.tuple).?.data;
14721383
1473 try writer.writeAll("tuple{");1384 try writer.writeAll("tuple{");
1474 for (tuple.types, 0..) |field_ty, i| {1385 for (tuple.types, 0..) |field_ty, i| {
1475 if (i != 0) try writer.writeAll(", ");1386 if (i != 0) try writer.writeAll(", ");
1476 const val = tuple.values[i];1387 const val = tuple.values[i];
1477 if (val.ip_index != .unreachable_value) {1388 if (val.ip_index != .unreachable_value) {
1478 try writer.writeAll("comptime ");1389 try writer.writeAll("comptime ");
1479 }1390 }
1480 try print(field_ty, writer, mod);1391 try print(field_ty, writer, mod);
1481 if (val.ip_index != .unreachable_value) {1392 if (val.ip_index != .unreachable_value) {
1482 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});1393 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1394 }
1483 }1395 }
1484 }1396 try writer.writeAll("}");
1485 try writer.writeAll("}");1397 },
1486 },1398 .anon_struct => {
1487 .anon_struct => {1399 const anon_struct = ty.castTag(.anon_struct).?.data;
1488 const anon_struct = ty.castTag(.anon_struct).?.data;
14891400
1490 try writer.writeAll("struct{");1401 try writer.writeAll("struct{");
1491 for (anon_struct.types, 0..) |field_ty, i| {1402 for (anon_struct.types, 0..) |field_ty, i| {
1492 if (i != 0) try writer.writeAll(", ");1403 if (i != 0) try writer.writeAll(", ");
1493 const val = anon_struct.values[i];1404 const val = anon_struct.values[i];
1494 if (val.ip_index != .unreachable_value) {1405 if (val.ip_index != .unreachable_value) {
1495 try writer.writeAll("comptime ");1406 try writer.writeAll("comptime ");
1496 }1407 }
1497 try writer.writeAll(anon_struct.names[i]);1408 try writer.writeAll(anon_struct.names[i]);
1498 try writer.writeAll(": ");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) {1413 if (val.ip_index != .unreachable_value) {
1503 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});1414 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
1415 }
1504 }1416 }
1505 }1417 try writer.writeAll("}");
1506 try writer.writeAll("}");1418 },
1507 },
15081419
1509 .pointer => {1420 .pointer => {
1510 const info = ty.ptrInfo(mod);1421 const info = ty.ptrInfo(mod);
15111422
1512 if (info.sentinel) |s| switch (info.size) {1423 if (info.sentinel) |s| switch (info.size) {
1513 .One, .C => unreachable,1424 .One, .C => unreachable,
1514 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),1425 .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1515 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),1426 .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
1516 } else switch (info.size) {1427 } else switch (info.size) {
1517 .One => try writer.writeAll("*"),1428 .One => try writer.writeAll("*"),
1518 .Many => try writer.writeAll("[*]"),1429 .Many => try writer.writeAll("[*]"),
1519 .C => try writer.writeAll("[*c]"),1430 .C => try writer.writeAll("[*c]"),
1520 .Slice => try writer.writeAll("[]"),1431 .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});
1528 }1432 }
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) {1441 if (info.bit_offset != 0 or info.host_size != 0) {
1531 try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });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(") ");
1532 }1450 }
1533 if (info.vector_index == .runtime) {1451 if (info.@"addrspace" != .generic) {
1534 try writer.writeAll(":?");1452 try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});
1535 } else if (info.vector_index != .none) {
1536 try writer.print(":{d}", .{@enumToInt(info.vector_index)});
1537 }1453 }
1538 try writer.writeAll(") ");1454 if (!info.mutable) try writer.writeAll("const ");
1539 }1455 if (info.@"volatile") try writer.writeAll("volatile ");
1540 if (info.@"addrspace" != .generic) {1456 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
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 },
15491457
1550 .optional => {1458 try print(info.pointee_type, writer, mod);
1551 const child_type = ty.castTag(.optional).?.data;1459 },
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 }
15841460
1585 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {1461 .optional => {
1586 if (self.ip_index != .none) return self.ip_index.toValue();1462 const child_type = ty.castTag(.optional).?.data;
1587 switch (self.tag()) {1463 try writer.writeByte('?');
1588 .inferred_alloc_const => unreachable,1464 try print(child_type, writer, mod);
1589 .inferred_alloc_mut => unreachable,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,
1590 else => return Value.Tag.ty.create(allocator, self),1589 else => return Value.Tag.ty.create(allocator, self),
1591 }1590 }
1592 }1591 }
...@@ -1610,240 +1609,244 @@ pub const Type = struct {...@@ -1610,240 +1609,244 @@ pub const Type = struct {
1610 ignore_comptime_only: bool,1609 ignore_comptime_only: bool,
1611 strat: AbiAlignmentAdvancedStrat,1610 strat: AbiAlignmentAdvancedStrat,
1612 ) RuntimeBitsError!bool {1611 ) RuntimeBitsError!bool {
1613 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {1612 switch (ty.ip_index) {
1614 .int_type => |int_type| return int_type.bits != 0,1613 // False because it is a comptime-only type.
1615 .ptr_type => |ptr_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
1616 // Pointers to zero-bit types still have a runtime address; however, pointers1626 // Pointers to zero-bit types still have a runtime address; however, pointers
1617 // to comptime-only types do not, with the exception of function pointers.1627 // to comptime-only types do not, with the exception of function pointers.
1618 if (ignore_comptime_only) return true;1628 .anyframe_T,
1619 const child_ty = ptr_type.elem_type.toType();1629 .pointer,
1620 if (child_ty.zigTypeTag(mod) == .Fn) return !child_ty.fnInfo().is_generic;1630 => {
1621 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));1631 if (ignore_comptime_only) {
1622 return !comptimeOnly(ty, mod);1632 return true;
1623 },1633 } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) {
1624 .array_type => |array_type| {1634 return !ty.childType(mod).fnInfo().is_generic;
1625 if (array_type.sentinel != .none) {1635 } else if (strat == .sema) {
1626 return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);1636 return !(try strat.sema.typeRequiresComptime(ty));
1627 } else {1637 } else {
1628 return array_type.len > 0 and1638 return !comptimeOnly(ty, mod);
1629 try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);1639 }
1630 }1640 },
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,
16841641
1685 // These are false because they are comptime-only types.1642 // These are false because they are comptime-only types.
1686 .void,1643 .empty_struct,
1687 .type,1644 // These are function *bodies*, not pointers.
1688 .comptime_int,1645 // Special exceptions have to be made when emitting functions due to
1689 .comptime_float,1646 // this returning false.
1690 .noreturn,1647 .function,
1691 .null,1648 => return false,
1692 .undefined,
1693 .enum_literal,
1694 .type_info,
1695 => false,
16961649
1697 .generic_poison => unreachable,1650 .optional => {
1698 .var_args_param => unreachable,1651 const child_ty = ty.optionalChild(mod);
1699 },1652 if (child_ty.isNoReturn()) {
1700 .struct_type => @panic("TODO"),1653 // Then the optional is comptime-known to be null.
1701 .union_type => @panic("TODO"),1654 return false;
1702 .simple_value => unreachable,1655 }
1703 .extern_func => unreachable,1656 if (ignore_comptime_only) {
1704 .int => unreachable,1657 return true;
1705 .enum_tag => unreachable, // it's a value, not a type1658 } else if (strat == .sema) {
1706 };1659 return !(try strat.sema.typeRequiresComptime(child_ty));
1707 switch (ty.tag()) {1660 } else {
1708 .error_set_inferred,1661 return !comptimeOnly(child_ty, mod);
17091662 }
1710 .@"opaque",1663 },
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 },
17321664
1733 // These are false because they are comptime-only types.1665 .@"struct" => {
1734 .empty_struct,1666 const struct_obj = ty.castTag(.@"struct").?.data;
1735 .empty_struct_literal,1667 if (struct_obj.status == .field_types_wip) {
1736 // These are function *bodies*, not pointers.1668 // In this case, we guess that hasRuntimeBits() for this type is true,
1737 // Special exceptions have to be made when emitting functions due to1669 // and then later if our guess was incorrect, we emit a compile error.
1738 // this returning false.1670 struct_obj.assumed_runtime_bits = true;
1739 .function,1671 return true;
1740 => return false,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 => {1687 .enum_full => {
1743 const child_ty = ty.optionalChild(mod);1688 const enum_full = ty.castTag(.enum_full).?.data;
1744 if (child_ty.isNoReturn()) {1689 return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1745 // Then the optional is comptime-known to be null.1690 },
1746 return false;1691 .enum_simple => {
1747 }1692 const enum_simple = ty.castTag(.enum_simple).?.data;
1748 if (ignore_comptime_only) {1693 return enum_simple.fields.count() >= 2;
1749 return true;1694 },
1750 } else if (strat == .sema) {1695 .enum_numbered, .enum_nonexhaustive => {
1751 return !(try strat.sema.typeRequiresComptime(child_ty));1696 const int_tag_ty = try ty.intTagType(mod);
1752 } else {1697 return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
1753 return !comptimeOnly(child_ty, mod);1698 },
1754 }
1755 },
17561699
1757 .@"struct" => {1700 .@"union" => {
1758 const struct_obj = ty.castTag(.@"struct").?.data;1701 const union_obj = ty.castTag(.@"union").?.data;
1759 if (struct_obj.status == .field_types_wip) {1702 if (union_obj.status == .field_types_wip) {
1760 // In this case, we guess that hasRuntimeBits() for this type is true,1703 // 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.1704 // and then later if our guess was incorrect, we emit a compile error.
1762 struct_obj.assumed_runtime_bits = true;1705 union_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))
1773 return true;1706 return true;
1774 } else {1707 }
1775 return false;1708 switch (strat) {
1776 }1709 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1777 },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 => {1726 switch (strat) {
1780 const enum_full = ty.castTag(.enum_full).?.data;1727 .sema => |sema| _ = try sema.resolveTypeFields(ty),
1781 return enum_full.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);1728 .eager => assert(union_obj.haveFieldTypes()),
1782 },1729 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
1783 .enum_simple => {1730 }
1784 const enum_simple = ty.castTag(.enum_simple).?.data;1731 for (union_obj.fields.values()) |value| {
1785 return enum_simple.fields.count() >= 2;1732 if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
1786 },1733 return true;
1787 .enum_numbered, .enum_nonexhaustive => {1734 } else {
1788 const int_tag_ty = try ty.intTagType(mod);1735 return false;
1789 return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);1736 }
1790 },1737 },
17911738
1792 .@"union" => {1739 .array => return ty.arrayLen(mod) != 0 and
1793 const union_obj = ty.castTag(.@"union").?.data;1740 try ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
1794 if (union_obj.status == .field_types_wip) {1741 .array_sentinel => return ty.childType(mod).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
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 }
18171742
1818 switch (strat) {1743 .tuple, .anon_struct => {
1819 .sema => |sema| _ = try sema.resolveTypeFields(ty),1744 const tuple = ty.tupleFields();
1820 .eager => assert(union_obj.haveFieldTypes()),1745 for (tuple.types, 0..) |field_ty, i| {
1821 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,1746 const val = tuple.values[i];
1822 }1747 if (val.ip_index != .unreachable_value) continue; // comptime field
1823 for (union_obj.fields.values()) |value| {1748 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
1824 if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))1749 }
1825 return true;
1826 } else {
1827 return false;1750 return false;
1828 }1751 },
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),
18341752
1835 .tuple, .anon_struct => {1753 .inferred_alloc_const => unreachable,
1836 const tuple = ty.tupleFields();1754 .inferred_alloc_mut => unreachable,
1837 for (tuple.types, 0..) |field_ty, i| {1755 },
1838 const val = tuple.values[i];1756 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1839 if (val.ip_index != .unreachable_value) continue; // comptime field1757 .int_type => |int_type| return int_type.bits != 0,
1840 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;1758 .ptr_type => |ptr_type| {
1841 }1759 // Pointers to zero-bit types still have a runtime address; however, pointers
1842 return false;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
1843 },1849 },
1844
1845 .inferred_alloc_const => unreachable,
1846 .inferred_alloc_mut => unreachable,
1847 }1850 }
1848 }1851 }
18491852
...@@ -1851,104 +1854,107 @@ pub const Type = struct {...@@ -1851,104 +1854,107 @@ pub const Type = struct {
1851 /// readFrom/writeToMemory are supported only for types with a well-1854 /// readFrom/writeToMemory are supported only for types with a well-
1852 /// defined memory layout1855 /// defined memory layout
1853 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {1856 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
1854 if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {1857 return switch (ty.ip_index) {
1855 .int_type => true,1858 .empty_struct_type => false,
1856 .ptr_type => true,1859
1857 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),1860 .none => switch (ty.tag()) {
1858 .vector_type => true,1861 .pointer,
1859 .opt_type => |child| child.toType().isPtrLikeOptional(mod),1862 .enum_numbered,
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,
1881 => true,1863 => true,
18821864
1883 .anyerror,1865 .error_set,
1884 .@"anyframe",1866 .error_set_single,
1885 .anyopaque,1867 .error_set_inferred,
1886 .atomic_order,1868 .error_set_merged,
1887 .atomic_rmw_op,1869 .@"opaque",
1888 .calling_convention,1870 // These are function bodies, not function pointers.
1889 .address_space,1871 .function,
1890 .float_mode,1872 .enum_simple,
1891 .reduce_op,1873 .error_union,
1892 .call_modifier,1874 .anyframe_T,
1893 .prefetch_options,1875 .tuple,
1894 .export_options,1876 .anon_struct,
1895 .extern_options,1877 .empty_struct,
1896 .type,
1897 .comptime_int,
1898 .comptime_float,
1899 .noreturn,
1900 .null,
1901 .undefined,
1902 .enum_literal,
1903 .type_info,
1904 .generic_poison,
1905 => false,1878 => false,
19061879
1907 .var_args_param => unreachable,1880 .enum_full,
1908 },1881 .enum_nonexhaustive,
1909 .struct_type => @panic("TODO"),1882 => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred,
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,
19201883
1921 .error_set,1884 .inferred_alloc_mut => unreachable,
1922 .error_set_single,1885 .inferred_alloc_const => unreachable,
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,
19361886
1937 .enum_full,1887 .array,
1938 .enum_nonexhaustive,1888 .array_sentinel,
1939 => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred,1889 => ty.childType(mod).hasWellDefinedLayout(mod),
19401890
1941 .inferred_alloc_mut => unreachable,1891 .optional => ty.isPtrLikeOptional(mod),
1942 .inferred_alloc_const => unreachable,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,1925 .anyerror,
1945 .array_sentinel,1926 .@"anyframe",
1946 => ty.childType(mod).hasWellDefinedLayout(mod),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 .var_args_param => unreachable,
1949 .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto,1950 },
1950 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,1951 .struct_type => @panic("TODO"),
1951 .union_tagged => false,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 },
1952 };1958 };
1953 }1959 }
19541960
...@@ -2120,232 +2126,232 @@ pub const Type = struct {...@@ -2120,232 +2126,232 @@ pub const Type = struct {
2120 else => null,2126 else => null,
2121 };2127 };
21222128
2123 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {2129 switch (ty.ip_index) {
2124 .int_type => |int_type| {2130 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },
2125 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };2131 .none => switch (ty.tag()) {
2126 return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) };2132 .@"opaque" => return AbiAlignmentAdvanced{ .scalar = 1 },
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 },
21412133
2142 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),2134 // represents machine code; not a pointer
2143 .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),2135 .function => {
2144 .simple_type => |t| switch (t) {2136 const alignment = ty.castTag(.function).?.data.alignment;
2145 .bool,2137 if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment };
2146 .atomic_order,2138 return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) };
2147 .atomic_rmw_op,2139 },
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 },
21562140
2157 .usize,2141 .pointer,
2158 .isize,2142 .anyframe_T,
2159 .export_options,
2160 .extern_options,
2161 .@"anyframe",
2162 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },2143 => 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
2196 // TODO revisit this when we have the concept of the error tag type2145 // TODO revisit this when we have the concept of the error tag type
2197 .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },2146 .error_set_inferred,
21982147 .error_set_single,
2199 .void,2148 .error_set,
2200 .type,2149 .error_set_merged,
2201 .comptime_int,2150 => return AbiAlignmentAdvanced{ .scalar = 2 },
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) },
22342151
2235 // TODO revisit this when we have the concept of the error tag type2152 .array, .array_sentinel => return ty.childType(mod).abiAlignmentAdvanced(mod, strat),
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),
22432153
2244 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),2154 .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
2245 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),2155 .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
22462156
2247 .@"struct" => {2157 .@"struct" => {
2248 const struct_obj = ty.castTag(.@"struct").?.data;2158 const struct_obj = ty.castTag(.@"struct").?.data;
2249 if (opt_sema) |sema| {2159 if (opt_sema) |sema| {
2250 if (struct_obj.status == .field_types_wip) {2160 if (struct_obj.status == .field_types_wip) {
2251 // We'll guess "pointer-aligned", if the struct has an2161 // We'll guess "pointer-aligned", if the struct has an
2252 // underaligned pointer field then some allocations2162 // underaligned pointer field then some allocations
2253 // might require explicit alignment.2163 // might require explicit alignment.
2254 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };2164 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
2165 }
2166 _ = try sema.resolveTypeFields(ty);
2255 }2167 }
2256 _ = try sema.resolveTypeFields(ty);2168 if (!struct_obj.haveFieldTypes()) switch (strat) {
2257 }2169 .eager => unreachable, // struct layout not resolved
2258 if (!struct_obj.haveFieldTypes()) switch (strat) {2170 .sema => unreachable, // handled above
2259 .eager => unreachable, // struct layout not resolved2171 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2260 .sema => unreachable, // handled above2172 };
2261 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },2173 if (struct_obj.layout == .Packed) {
2262 };2174 switch (strat) {
2263 if (struct_obj.layout == .Packed) {2175 .sema => |sema| try sema.resolveTypeLayout(ty),
2264 switch (strat) {2176 .lazy => |arena| {
2265 .sema => |sema| try sema.resolveTypeLayout(ty),2177 if (!struct_obj.haveLayout()) {
2266 .lazy => |arena| {2178 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
2267 if (!struct_obj.haveLayout()) {2179 }
2268 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };2180 },
2269 }2181 .eager => {},
2270 },2182 }
2271 .eager => {},2183 assert(struct_obj.haveLayout());
2184 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) };
2272 }2185 }
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)2187 const fields = ty.structFields();
2286 field.abi_align2188 var big_align: u32 = 0;
2287 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {2189 for (fields.values()) |field| {
2288 .scalar => |a| a,2190 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
2289 .val => switch (strat) {2191 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
2290 .eager => unreachable, // struct layout not resolved2192 else => |e| return e,
2291 .sema => unreachable, // handled above2193 })) continue;
2292 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },2194
2293 },2195 const field_align = if (field.abi_align != 0)
2294 };2196 field.abi_align
2295 big_align = @max(big_align, field_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.2219 .tuple, .anon_struct => {
2298 if (struct_obj.layout == .Extern or target.ofmt == .c) {2220 const tuple = ty.tupleFields();
2299 if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {2221 var big_align: u32 = 0;
2300 // The C ABI requires 128 bit integer fields of structs2222 for (tuple.types, 0..) |field_ty, i| {
2301 // to be 16-bytes aligned.2223 const val = tuple.values[i];
2302 big_align = @max(big_align, 16);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 },
2303 }2234 }
2304 }2235 }
2305 }2236 return AbiAlignmentAdvanced{ .scalar = big_align };
2306 return AbiAlignmentAdvanced{ .scalar = big_align };2237 },
2307 },
23082238
2309 .tuple, .anon_struct => {2239 .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => {
2310 const tuple = ty.tupleFields();2240 const int_tag_ty = try ty.intTagType(mod);
2311 var big_align: u32 = 0;2241 return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) };
2312 for (tuple.types, 0..) |field_ty, i| {2242 },
2313 const val = tuple.values[i];2243 .@"union" => {
2314 if (val.ip_index != .unreachable_value) continue; // comptime field2244 const union_obj = ty.castTag(.@"union").?.data;
2315 if (!(field_ty.hasRuntimeBits(mod))) continue;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)) {2254 .inferred_alloc_const,
2318 .scalar => |field_align| big_align = @max(big_align, field_align),2255 .inferred_alloc_mut,
2319 .val => switch (strat) {2256 => unreachable,
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 };
2327 },2257 },
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 => {2277 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
2330 const int_tag_ty = try ty.intTagType(mod);2278 .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
2331 return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) };2279 .simple_type => |t| switch (t) {
2332 },2280 .bool,
2333 .@"union" => {2281 .atomic_order,
2334 const union_obj = ty.castTag(.@"union").?.data;2282 .atomic_rmw_op,
2335 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, false);2283 .calling_convention,
2336 },2284 .address_space,
2337 .union_safety_tagged, .union_tagged => {2285 .float_mode,
2338 const union_obj = ty.cast(Payload.Union).?.data;2286 .reduce_op,
2339 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, true);2287 .call_modifier,
2340 },2288 .prefetch_options,
2289 .anyopaque,
2290 => return AbiAlignmentAdvanced{ .scalar = 1 },
23412291
2342 .empty_struct,2292 .usize,
2343 .empty_struct_literal,2293 .isize,
2344 => return AbiAlignmentAdvanced{ .scalar = 0 },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,2331 // TODO revisit this when we have the concept of the error tag type
2347 .inferred_alloc_mut,2332 .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },
2348 => unreachable,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 },
2349 }2355 }
2350 }2356 }
23512357
...@@ -2506,255 +2512,256 @@ pub const Type = struct {...@@ -2506,255 +2512,256 @@ pub const Type = struct {
2506 ) Module.CompileError!AbiSizeAdvanced {2512 ) Module.CompileError!AbiSizeAdvanced {
2507 const target = mod.getTarget();2513 const target = mod.getTarget();
25082514
2509 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {2515 switch (ty.ip_index) {
2510 .int_type => |int_type| {2516 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
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 },
25492517
2550 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),2518 .none => switch (ty.tag()) {
2551 .error_union_type => @panic("TODO"),2519 .function => unreachable, // represents machine code; not a pointer
2552 .simple_type => |t| switch (t) {2520 .@"opaque" => unreachable, // no size available
2553 .bool,2521 .inferred_alloc_const => unreachable,
2554 .atomic_order,2522 .inferred_alloc_mut => unreachable,
2555 .atomic_rmw_op,2523
2556 .calling_convention,2524 .empty_struct => return AbiSizeAdvanced{ .scalar = 0 },
2557 .address_space,2525
2558 .float_mode,2526 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {
2559 .reduce_op,2527 .Packed => {
2560 .call_modifier,2528 const struct_obj = ty.castTag(.@"struct").?.data;
2561 => return AbiSizeAdvanced{ .scalar = 1 },2529 switch (strat) {
25622530 .sema => |sema| try sema.resolveTypeLayout(ty),
2563 .f16 => return AbiSizeAdvanced{ .scalar = 2 },2531 .lazy => |arena| {
2564 .f32 => return AbiSizeAdvanced{ .scalar = 4 },2532 if (!struct_obj.haveLayout()) {
2565 .f64 => return AbiSizeAdvanced{ .scalar = 8 },2533 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
2566 .f128 => return AbiSizeAdvanced{ .scalar = 16 },2534 }
2567 .f80 => switch (target.c_type_bit_size(.longdouble)) {2535 },
2568 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },2536 .eager => {},
2537 }
2538 assert(struct_obj.haveLayout());
2539 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) };
2540 },
2569 else => {2541 else => {
2570 const u80_ty: Type = .{2542 switch (strat) {
2571 .ip_index = .u80_type,2543 .sema => |sema| try sema.resolveTypeLayout(ty),
2572 .legacy = undefined,2544 .lazy => |arena| {
2573 };2545 if (ty.castTag(.@"struct")) |payload| {
2574 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };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) };
2575 },2559 },
2576 },2560 },
25772561
2578 .usize,2562 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
2579 .isize,2563 const int_tag_ty = try ty.intTagType(mod);
2580 .@"anyframe",2564 return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) };
2581 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },2565 },
25822566 .@"union" => {
2583 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },2567 const union_obj = ty.castTag(.@"union").?.data;
2584 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },2568 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, false);
2585 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },2569 },
2586 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },2570 .union_safety_tagged, .union_tagged => {
2587 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },2571 const union_obj = ty.cast(Payload.Union).?.data;
2588 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },2572 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, true);
2589 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },2573 },
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 },
26332574
2634 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {2575 .array => {
2635 .Packed => {2576 const payload = ty.castTag(.array).?.data;
2636 const struct_obj = ty.castTag(.@"struct").?.data;2577 switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) {
2637 switch (strat) {2578 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },
2638 .sema => |sema| try sema.resolveTypeLayout(ty),2579 .val => switch (strat) {
2639 .lazy => |arena| {2580 .sema => unreachable,
2640 if (!struct_obj.haveLayout()) {2581 .eager => unreachable,
2641 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };2582 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2642 }
2643 },2583 },
2644 .eager => {},
2645 }2584 }
2646 assert(struct_obj.haveLayout());
2647 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) };
2648 },2585 },
2649 else => {2586 .array_sentinel => {
2650 switch (strat) {2587 const payload = ty.castTag(.array_sentinel).?.data;
2651 .sema => |sema| try sema.resolveTypeLayout(ty),2588 switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) {
2652 .lazy => |arena| {2589 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size },
2653 if (ty.castTag(.@"struct")) |payload| {2590 .val => switch (strat) {
2654 const struct_obj = payload.data;2591 .sema => unreachable,
2655 if (!struct_obj.haveLayout()) {2592 .eager => unreachable,
2656 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };2593 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
2657 }
2658 }
2659 },2594 },
2660 .eager => {},
2661 }2595 }
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) };
2667 },2596 },
2668 },
26692597
2670 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {2598 .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
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 },
26822599
2683 .array => {2600 .pointer => switch (ty.castTag(.pointer).?.data.size) {
2684 const payload = ty.castTag(.array).?.data;2601 .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
2685 switch (try payload.elem_type.abiSizeAdvanced(mod, strat)) {2602 else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2686 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },2603 },
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 },
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) {2612 .optional => return ty.abiSizeAdvancedOptional(mod, strat),
2709 .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
2710 else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2711 },
27122613
2713 // TODO revisit this when we have the concept of the error tag type2614 .error_union => {
2714 .error_set_inferred,2615 // This code needs to be kept in sync with the equivalent switch prong
2715 .error_set,2616 // in abiAlignmentAdvanced.
2716 .error_set_merged,2617 const data = ty.castTag(.error_union).?.data;
2717 .error_set_single,2618 const code_size = abiSize(Type.anyerror, mod);
2718 => return AbiSizeAdvanced{ .scalar = 2 },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 => {2693 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
2723 // This code needs to be kept in sync with the equivalent switch prong2694 .error_union_type => @panic("TODO"),
2724 // in abiAlignmentAdvanced.2695 .simple_type => |t| switch (t) {
2725 const data = ty.castTag(.error_union).?.data;2696 .bool,
2726 const code_size = abiSize(Type.anyerror, mod);2697 .atomic_order,
2727 if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {2698 .atomic_rmw_op,
2728 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },2699 .calling_convention,
2729 else => |e| return e,2700 .address_space,
2730 })) {2701 .float_mode,
2731 // Same as anyerror.2702 .reduce_op,
2732 return AbiSizeAdvanced{ .scalar = code_size };2703 .call_modifier,
2733 }2704 => return AbiSizeAdvanced{ .scalar = 1 },
2734 const code_align = abiAlignment(Type.anyerror, mod);2705
2735 const payload_align = abiAlignment(data.payload, mod);2706 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
2736 const payload_size = switch (try data.payload.abiSizeAdvanced(mod, strat)) {2707 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
2737 .scalar => |elem_size| elem_size,2708 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
2738 .val => switch (strat) {2709 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
2739 .sema => unreachable,2710 .f80 => switch (target.c_type_bit_size(.longdouble)) {
2740 .eager => unreachable,2711 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
2741 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },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 },
2742 },2719 },
2743 };
27442720
2745 var size: u64 = 0;2721 .usize,
2746 if (code_align > payload_align) {2722 .isize,
2747 size += code_size;2723 .@"anyframe",
2748 size = std.mem.alignForwardGeneric(u64, size, payload_align);2724 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2749 size += payload_size;2725
2750 size = std.mem.alignForwardGeneric(u64, size, code_align);2726 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
2751 } else {2727 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
2752 size += payload_size;2728 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
2753 size = std.mem.alignForwardGeneric(u64, size, code_align);2729 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
2754 size += code_size;2730 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
2755 size = std.mem.alignForwardGeneric(u64, size, payload_align);2731 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
2756 }2732 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
2757 return AbiSizeAdvanced{ .scalar = size };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
2758 },2765 },
2759 }2766 }
2760 }2767 }
...@@ -2929,7 +2936,6 @@ pub const Type = struct {...@@ -2929,7 +2936,6 @@ pub const Type = struct {
2929 switch (ty.tag()) {2936 switch (ty.tag()) {
2930 .function => unreachable, // represents machine code; not a pointer2937 .function => unreachable, // represents machine code; not a pointer
2931 .empty_struct => unreachable,2938 .empty_struct => unreachable,
2932 .empty_struct_literal => unreachable,
2933 .inferred_alloc_const => unreachable,2939 .inferred_alloc_const => unreachable,
2934 .inferred_alloc_mut => unreachable,2940 .inferred_alloc_mut => unreachable,
2935 .@"opaque" => unreachable,2941 .@"opaque" => unreachable,
...@@ -3490,12 +3496,16 @@ pub const Type = struct {...@@ -3490,12 +3496,16 @@ pub const Type = struct {
3490 }3496 }
34913497
3492 pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout {3498 pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout {
3493 return switch (ty.tag()) {3499 return switch (ty.ip_index) {
3494 .tuple, .empty_struct_literal, .anon_struct => .Auto,3500 .empty_struct_type => .Auto,
3495 .@"struct" => ty.castTag(.@"struct").?.data.layout,3501 .none => switch (ty.tag()) {
3496 .@"union" => ty.castTag(.@"union").?.data.layout,3502 .tuple, .anon_struct => .Auto,
3497 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,3503 .@"struct" => ty.castTag(.@"struct").?.data.layout,
3498 .union_tagged => ty.castTag(.union_tagged).?.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 },
3499 else => unreachable,3509 else => unreachable,
3500 };3510 };
3501 }3511 }
...@@ -3610,13 +3620,14 @@ pub const Type = struct {...@@ -3610,13 +3620,14 @@ pub const Type = struct {
36103620
3611 pub fn arrayLenIp(ty: Type, ip: InternPool) u64 {3621 pub fn arrayLenIp(ty: Type, ip: InternPool) u64 {
3612 return switch (ty.ip_index) {3622 return switch (ty.ip_index) {
3623 .empty_struct_type => 0,
3613 .none => switch (ty.tag()) {3624 .none => switch (ty.tag()) {
3614 .array => ty.castTag(.array).?.data.len,3625 .array => ty.castTag(.array).?.data.len,
3615 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,3626 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,
3616 .tuple => ty.castTag(.tuple).?.data.types.len,3627 .tuple => ty.castTag(.tuple).?.data.types.len,
3617 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,3628 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
3618 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),3629 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
3619 .empty_struct, .empty_struct_literal => 0,3630 .empty_struct => 0,
36203631
3621 else => unreachable,3632 else => unreachable,
3622 },3633 },
...@@ -3649,10 +3660,10 @@ pub const Type = struct {...@@ -3649,10 +3660,10 @@ pub const Type = struct {
3649 /// Asserts the type is an array, pointer or vector.3660 /// Asserts the type is an array, pointer or vector.
3650 pub fn sentinel(ty: Type, mod: *const Module) ?Value {3661 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
3651 return switch (ty.ip_index) {3662 return switch (ty.ip_index) {
3663 .empty_struct_type => null,
3652 .none => switch (ty.tag()) {3664 .none => switch (ty.tag()) {
3653 .array,3665 .array,
3654 .tuple,3666 .tuple,
3655 .empty_struct_literal,
3656 .@"struct",3667 .@"struct",
3657 => null,3668 => null,
36583669
...@@ -3951,197 +3962,200 @@ pub const Type = struct {...@@ -3951,197 +3962,200 @@ pub const Type = struct {
3951 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {3962 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
3952 var ty = starting_type;3963 var ty = starting_type;
39533964
3954 if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {3965 while (true) switch (ty.ip_index) {
3955 .int_type => |int_type| {3966 .empty_struct_type => return Value.empty_struct,
3956 if (int_type.bits == 0) {3967
3957 return try mod.intValue(ty, 0);3968 .none => switch (ty.tag()) {
3958 } else {3969 .error_union,
3959 return null;3970 .error_set_single,
3960 }3971 .error_set,
3961 },3972 .error_set_merged,
3962 .ptr_type => return null,3973 .function,
3963 .array_type => |array_type| {3974 .array_sentinel,
3964 if (array_type.len == 0)3975 .error_set_inferred,
3965 return Value.initTag(.empty_array);3976 .@"opaque",
3966 if ((try array_type.child.toType().onePossibleValue(mod)) != null)3977 .anyframe_T,
3967 return Value.initTag(.the_only_possible_value);3978 .pointer,
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,
4020 => return null,3979 => return null,
40213980
4022 .void => return Value.void,3981 .optional => {
4023 .noreturn => return Value.@"unreachable",3982 const child_ty = ty.optionalChild(mod);
4024 .null => return Value.null,3983 if (child_ty.isNoReturn()) {
4025 .undefined => return Value.undef,3984 return Value.null;
3985 } else {
3986 return null;
3987 }
3988 },
40263989
4027 .generic_poison => unreachable,3990 .@"struct" => {
4028 .var_args_param => unreachable,3991 const s = ty.castTag(.@"struct").?.data;
4029 },3992 assert(s.haveFieldTypes());
4030 .struct_type => @panic("TODO"),3993 for (s.fields.values()) |field| {
4031 .union_type => @panic("TODO"),3994 if (field.is_comptime) continue;
4032 .simple_value => unreachable,3995 if ((try field.ty.onePossibleValue(mod)) != null) continue;
4033 .extern_func => unreachable,3996 return null;
4034 .int => unreachable,3997 }
4035 .enum_tag => unreachable, // it's a value, not a type3998 return Value.empty_struct;
4036 };3999 },
40374000
4038 while (true) switch (ty.tag()) {4001 .tuple, .anon_struct => {
4039 .error_union,4002 const tuple = ty.tupleFields();
4040 .error_set_single,4003 for (tuple.values, 0..) |val, i| {
4041 .error_set,4004 const is_comptime = val.ip_index != .unreachable_value;
4042 .error_set_merged,4005 if (is_comptime) continue;
4043 .function,4006 if ((try tuple.types[i].onePossibleValue(mod)) != null) continue;
4044 .array_sentinel,4007 return null;
4045 .error_set_inferred,4008 }
4046 .@"opaque",4009 return Value.empty_struct;
4047 .anyframe_T,4010 },
4048 .pointer,4011
4049 => return null,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 => {4063 .empty_struct => return Value.empty_struct,
4052 const child_ty = ty.optionalChild(mod);
4053 if (child_ty.isNoReturn()) {
4054 return Value.null;
4055 } else {
4056 return null;
4057 }
4058 },
40594064
4060 .@"struct" => {4065 .array => {
4061 const s = ty.castTag(.@"struct").?.data;4066 if (ty.arrayLen(mod) == 0)
4062 assert(s.haveFieldTypes());4067 return Value.initTag(.empty_array);
4063 for (s.fields.values()) |field| {4068 if ((try ty.childType(mod).onePossibleValue(mod)) != null)
4064 if (field.is_comptime) continue;4069 return Value.initTag(.the_only_possible_value);
4065 if ((try field.ty.onePossibleValue(mod)) != null) continue;
4066 return null;4070 return null;
4067 }4071 },
4068 return Value.initTag(.empty_struct_value);
4069 },
40704072
4071 .tuple, .anon_struct => {4073 .inferred_alloc_const => unreachable,
4072 const tuple = ty.tupleFields();4074 .inferred_alloc_mut => unreachable,
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);
4080 },4075 },
40814076 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4082 .enum_numbered => {4077 .int_type => |int_type| {
4083 const enum_numbered = ty.castTag(.enum_numbered).?.data;4078 if (int_type.bits == 0) {
4084 // An explicit tag type is always provided for enum_numbered.4079 return try mod.intValue(ty, 0);
4085 if (enum_numbered.tag_ty.hasRuntimeBits(mod)) {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);
4086 return null;4090 return null;
4087 }4091 },
4088 assert(enum_numbered.fields.count() == 1);4092 .vector_type => |vector_type| {
4089 return enum_numbered.values.keys()[0];4093 if (vector_type.len == 0) return Value.initTag(.empty_array);
4090 },4094 if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v;
4091 .enum_full => {
4092 const enum_full = ty.castTag(.enum_full).?.data;
4093 if (enum_full.tag_ty.hasRuntimeBits(mod)) {
4094 return null;4095 return null;
4095 }4096 },
4096 switch (enum_full.fields.count()) {4097 .opt_type => |child| {
4097 0 => return Value.@"unreachable",4098 if (child.toType().isNoReturn()) {
4098 1 => if (enum_full.values.count() == 0) {4099 return Value.null;
4099 return try mod.intValue(ty, 0); // auto-numbered
4100 } else {4100 } else {
4101 return enum_full.values.keys()[0];4101 return null;
4102 },4102 }
4103 else => return null,4103 },
4104 }4104 .error_union_type => return null,
4105 },4105 .simple_type => |t| switch (t) {
4106 .enum_simple => {4106 .f16,
4107 const enum_simple = ty.castTag(.enum_simple).?.data;4107 .f32,
4108 switch (enum_simple.fields.count()) {4108 .f64,
4109 0 => return Value.@"unreachable",4109 .f80,
4110 1 => return try mod.intValue(ty, 0),4110 .f128,
4111 else => return null,4111 .usize,
4112 }4112 .isize,
4113 },4113 .c_char,
4114 .enum_nonexhaustive => {4114 .c_short,
4115 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;4115 .c_ushort,
4116 if (!tag_ty.hasRuntimeBits(mod)) {4116 .c_int,
4117 return try mod.intValue(ty, 0);4117 .c_uint,
4118 } else {4118 .c_long,
4119 return null;4119 .c_ulong,
4120 }4120 .c_longlong,
4121 },4121 .c_ulonglong,
4122 .@"union", .union_safety_tagged, .union_tagged => {4122 .c_longdouble,
4123 const union_obj = ty.cast(Payload.Union).?.data;4123 .anyopaque,
4124 const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null;4124 .bool,
4125 if (union_obj.fields.count() == 0) return Value.@"unreachable";4125 .type,
4126 const only_field = union_obj.fields.values()[0];4126 .anyerror,
4127 const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null;4127 .comptime_int,
4128 _ = tag_val;4128 .comptime_float,
4129 _ = val_val;4129 .@"anyframe",
4130 return Value.initTag(.empty_struct_value);4130 .enum_literal,
4131 },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 => {4149 .generic_poison => unreachable,
4136 if (ty.arrayLen(mod) == 0)4150 .var_args_param => unreachable,
4137 return Value.initTag(.empty_array);4151 },
4138 if ((try ty.childType(mod).onePossibleValue(mod)) != null)4152 .struct_type => @panic("TODO"),
4139 return Value.initTag(.the_only_possible_value);4153 .union_type => @panic("TODO"),
4140 return null;4154 .simple_value => unreachable,
4155 .extern_func => unreachable,
4156 .int => unreachable,
4157 .enum_tag => unreachable, // it's a value, not a type
4141 },4158 },
4142
4143 .inferred_alloc_const => unreachable,
4144 .inferred_alloc_mut => unreachable,
4145 };4159 };
4146 }4160 }
41474161
...@@ -4150,159 +4164,161 @@ pub const Type = struct {...@@ -4150,159 +4164,161 @@ pub const Type = struct {
4150 /// TODO merge these implementations together with the "advanced" pattern seen4164 /// TODO merge these implementations together with the "advanced" pattern seen
4151 /// elsewhere in this file.4165 /// elsewhere in this file.
4152 pub fn comptimeOnly(ty: Type, mod: *const Module) bool {4166 pub fn comptimeOnly(ty: Type, mod: *const Module) bool {
4153 if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {4167 return switch (ty.ip_index) {
4154 .int_type => false,4168 .empty_struct_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,
42034169
4204 .type,4170 .none => switch (ty.tag()) {
4205 .comptime_int,4171 .empty_struct,
4206 .comptime_float,4172 .error_set,
4207 .null,4173 .error_set_single,
4208 .undefined,4174 .error_set_inferred,
4209 .enum_literal,4175 .error_set_merged,
4210 .type_info,4176 .@"opaque",
4211 => true,4177 .enum_simple,
4178 => false,
42124179
4213 .var_args_param => unreachable,4180 // These are function bodies, not function pointers.
4214 },4181 .function => true,
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 };
42224182
4223 return switch (ty.tag()) {4183 .inferred_alloc_mut => unreachable,
4224 .empty_struct_literal,4184 .inferred_alloc_const => unreachable,
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,
42334185
4234 // These are function bodies, not function pointers.4186 .array,
4235 .function => true,4187 .array_sentinel,
4188 => return ty.childType(mod).comptimeOnly(mod),
42364189
4237 .inferred_alloc_mut => unreachable,4190 .pointer => {
4238 .inferred_alloc_const => unreachable,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,4199 .optional => {
4241 .array_sentinel,4200 return ty.optionalChild(mod).comptimeOnly(mod);
4242 => return ty.childType(mod).comptimeOnly(mod),4201 },
42434202
4244 .pointer => {4203 .tuple, .anon_struct => {
4245 const child_ty = ty.childType(mod);4204 const tuple = ty.tupleFields();
4246 if (child_ty.zigTypeTag(mod) == .Fn) {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 }
4247 return false;4209 return false;
4248 } else {4210 },
4249 return child_ty.comptimeOnly(mod);
4250 }
4251 },
42524211
4253 .optional => {4212 .@"struct" => {
4254 return ty.optionalChild(mod).comptimeOnly(mod);4213 const struct_obj = ty.castTag(.@"struct").?.data;
4255 },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 => {4226 .@"union", .union_safety_tagged, .union_tagged => {
4258 const tuple = ty.tupleFields();4227 const union_obj = ty.cast(Type.Payload.Union).?.data;
4259 for (tuple.types, 0..) |field_ty, i| {4228 switch (union_obj.requires_comptime) {
4260 const have_comptime_val = tuple.values[i].ip_index != .unreachable_value;4229 .wip, .unknown => {
4261 if (!have_comptime_val and field_ty.comptimeOnly(mod)) return true;4230 // Return false to avoid incorrect dependency loops.
4262 }4231 // This will be handled correctly once merged with
4263 return false;4232 // `Sema.typeRequiresComptime`.
4264 },4233 return false;
4234 },
4235 .no => return false,
4236 .yes => return true,
4237 }
4238 },
42654239
4266 .@"struct" => {4240 .error_union => return ty.errorUnionPayload().comptimeOnly(mod),
4267 const struct_obj = ty.castTag(.@"struct").?.data;4241 .anyframe_T => {
4268 switch (struct_obj.requires_comptime) {4242 const child_ty = ty.castTag(.anyframe_T).?.data;
4269 .wip, .unknown => {4243 return child_ty.comptimeOnly(mod);
4270 // Return false to avoid incorrect dependency loops.4244 },
4271 // This will be handled correctly once merged with4245 .enum_numbered => {
4272 // `Sema.typeRequiresComptime`.4246 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
4273 return false;4247 return tag_ty.comptimeOnly(mod);
4274 },4248 },
4275 .no => return false,4249 .enum_full, .enum_nonexhaustive => {
4276 .yes => return true,4250 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
4277 }4251 return tag_ty.comptimeOnly(mod);
4252 },
4278 },4253 },
42794254 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
4280 .@"union", .union_safety_tagged, .union_tagged => {4255 .int_type => false,
4281 const union_obj = ty.cast(Type.Payload.Union).?.data;4256 .ptr_type => |ptr_type| {
4282 switch (union_obj.requires_comptime) {4257 const child_ty = ptr_type.elem_type.toType();
4283 .wip, .unknown => {4258 if (child_ty.zigTypeTag(mod) == .Fn) {
4284 // Return false to avoid incorrect dependency loops.
4285 // This will be handled correctly once merged with
4286 // `Sema.typeRequiresComptime`.
4287 return false;4259 return false;
4288 },4260 } else {
4289 .no => return false,4261 return child_ty.comptimeOnly(mod);
4290 .yes => return true,4262 }
4291 }4263 },
4292 },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),4305 .type,
4295 .anyframe_T => {4306 .comptime_int,
4296 const child_ty = ty.castTag(.anyframe_T).?.data;4307 .comptime_float,
4297 return child_ty.comptimeOnly(mod);4308 .null,
4298 },4309 .undefined,
4299 .enum_numbered => {4310 .enum_literal,
4300 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;4311 .type_info,
4301 return tag_ty.comptimeOnly(mod);4312 => true,
4302 },4313
4303 .enum_full, .enum_nonexhaustive => {4314 .var_args_param => unreachable,
4304 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;4315 },
4305 return tag_ty.comptimeOnly(mod);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
4306 },4322 },
4307 };4323 };
4308 }4324 }
...@@ -4575,15 +4591,19 @@ pub const Type = struct {...@@ -4575,15 +4591,19 @@ pub const Type = struct {
4575 }4591 }
45764592
4577 pub fn structFields(ty: Type) Module.Struct.Fields {4593 pub fn structFields(ty: Type) Module.Struct.Fields {
4578 switch (ty.tag()) {4594 return switch (ty.ip_index) {
4579 .empty_struct, .empty_struct_literal => return .{},4595 .empty_struct_type => .{},
4580 .@"struct" => {4596 .none => switch (ty.tag()) {
4581 const struct_obj = ty.castTag(.@"struct").?.data;4597 .empty_struct => .{},
4582 assert(struct_obj.haveFieldTypes());4598 .@"struct" => {
4583 return struct_obj.fields;4599 const struct_obj = ty.castTag(.@"struct").?.data;
4600 assert(struct_obj.haveFieldTypes());
4601 return struct_obj.fields;
4602 },
4603 else => unreachable,
4584 },4604 },
4585 else => unreachable,4605 else => unreachable,
4586 }4606 };
4587 }4607 }
45884608
4589 pub fn structFieldName(ty: Type, field_index: usize) []const u8 {4609 pub fn structFieldName(ty: Type, field_index: usize) []const u8 {
...@@ -4599,17 +4619,21 @@ pub const Type = struct {...@@ -4599,17 +4619,21 @@ pub const Type = struct {
4599 }4619 }
46004620
4601 pub fn structFieldCount(ty: Type) usize {4621 pub fn structFieldCount(ty: Type) usize {
4602 switch (ty.tag()) {4622 return switch (ty.ip_index) {
4603 .@"struct" => {4623 .empty_struct_type => 0,
4604 const struct_obj = ty.castTag(.@"struct").?.data;4624 .none => switch (ty.tag()) {
4605 assert(struct_obj.haveFieldTypes());4625 .@"struct" => {
4606 return struct_obj.fields.count();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,
4607 },4634 },
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,
4611 else => unreachable,4635 else => unreachable,
4612 }4636 };
4613 }4637 }
46144638
4615 /// Supports structs and unions.4639 /// Supports structs and unions.
...@@ -4927,10 +4951,6 @@ pub const Type = struct {...@@ -4927,10 +4951,6 @@ pub const Type = struct {
4927 return ty.ip_index == .generic_poison_type;4951 return ty.ip_index == .generic_poison_type;
4928 }4952 }
49294953
4930 pub fn isVarArgsParam(ty: Type) bool {
4931 return ty.ip_index == .none and ty.tag() == .var_args_param;
4932 }
4933
4934 /// This enum does not directly correspond to `std.builtin.TypeId` because4954 /// This enum does not directly correspond to `std.builtin.TypeId` because
4935 /// it has extra enum tags in it, as a way of using less memory. For example,4955 /// it has extra enum tags in it, as a way of using less memory. For example,
4936 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types4956 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
...@@ -4938,8 +4958,6 @@ pub const Type = struct {...@@ -4938,8 +4958,6 @@ pub const Type = struct {
4938 /// with different enum tags, because the the former requires more payload data than the latter.4958 /// with different enum tags, because the the former requires more payload data than the latter.
4939 /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.4959 /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.
4940 pub const Tag = enum(usize) {4960 pub const Tag = enum(usize) {
4941 /// Same as `empty_struct` except it has an empty namespace.
4942 empty_struct_literal,
4943 /// This is a special value that tracks a set of types that have been stored4961 /// This is a special value that tracks a set of types that have been stored
4944 /// to an inferred allocation. It does not support most of the normal type queries.4962 /// to an inferred allocation. It does not support most of the normal type queries.
4945 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.4963 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
...@@ -4982,7 +5000,6 @@ pub const Type = struct {...@@ -4982,7 +5000,6 @@ pub const Type = struct {
4982 return switch (t) {5000 return switch (t) {
4983 .inferred_alloc_const,5001 .inferred_alloc_const,
4984 .inferred_alloc_mut,5002 .inferred_alloc_mut,
4985 .empty_struct_literal,
4986 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),5003 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
49875004
4988 .optional,5005 .optional,
...@@ -5038,33 +5055,36 @@ pub const Type = struct {...@@ -5038,33 +5055,36 @@ pub const Type = struct {
50385055
5039 pub fn isTuple(ty: Type) bool {5056 pub fn isTuple(ty: Type) bool {
5040 return switch (ty.ip_index) {5057 return switch (ty.ip_index) {
5058 .empty_struct_type => true,
5041 .none => switch (ty.tag()) {5059 .none => switch (ty.tag()) {
5042 .tuple, .empty_struct_literal => true,5060 .tuple => true,
5043 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,5061 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
5044 else => false,5062 else => false,
5045 },5063 },
5046 else => false, // TODO5064 else => false, // TODO struct
5047 };5065 };
5048 }5066 }
50495067
5050 pub fn isAnonStruct(ty: Type) bool {5068 pub fn isAnonStruct(ty: Type) bool {
5051 return switch (ty.ip_index) {5069 return switch (ty.ip_index) {
5070 .empty_struct_type => true,
5052 .none => switch (ty.tag()) {5071 .none => switch (ty.tag()) {
5053 .anon_struct, .empty_struct_literal => true,5072 .anon_struct => true,
5054 else => false,5073 else => false,
5055 },5074 },
5056 else => false, // TODO5075 else => false, // TODO struct
5057 };5076 };
5058 }5077 }
50595078
5060 pub fn isTupleOrAnonStruct(ty: Type) bool {5079 pub fn isTupleOrAnonStruct(ty: Type) bool {
5061 return switch (ty.ip_index) {5080 return switch (ty.ip_index) {
5081 .empty_struct_type => true,
5062 .none => switch (ty.tag()) {5082 .none => switch (ty.tag()) {
5063 .tuple, .empty_struct_literal, .anon_struct => true,5083 .tuple, .anon_struct => true,
5064 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,5084 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
5065 else => false,5085 else => false,
5066 },5086 },
5067 else => false, // TODO5087 else => false, // TODO struct
5068 };5088 };
5069 }5089 }
50705090
...@@ -5072,7 +5092,7 @@ pub const Type = struct {...@@ -5072,7 +5092,7 @@ pub const Type = struct {
5072 return switch (ty.ip_index) {5092 return switch (ty.ip_index) {
5073 .empty_struct => true,5093 .empty_struct => true,
5074 .none => switch (ty.tag()) {5094 .none => switch (ty.tag()) {
5075 .tuple, .empty_struct_literal => true,5095 .tuple => true,
5076 else => false,5096 else => false,
5077 },5097 },
5078 else => false, // TODO5098 else => false, // TODO
...@@ -5083,7 +5103,7 @@ pub const Type = struct {...@@ -5083,7 +5103,7 @@ pub const Type = struct {
5083 return switch (ty.ip_index) {5103 return switch (ty.ip_index) {
5084 .empty_struct => true,5104 .empty_struct => true,
5085 .none => switch (ty.tag()) {5105 .none => switch (ty.tag()) {
5086 .tuple, .empty_struct_literal, .anon_struct => true,5106 .tuple, .anon_struct => true,
5087 else => false,5107 else => false,
5088 },5108 },
5089 else => false,5109 else => false,
...@@ -5100,7 +5120,6 @@ pub const Type = struct {...@@ -5100,7 +5120,6 @@ pub const Type = struct {
5100 .types = ty.castTag(.anon_struct).?.data.types,5120 .types = ty.castTag(.anon_struct).?.data.types,
5101 .values = ty.castTag(.anon_struct).?.data.values,5121 .values = ty.castTag(.anon_struct).?.data.values,
5102 },5122 },
5103 .empty_struct_literal => .{ .types = &.{}, .values = &.{} },
5104 else => unreachable,5123 else => unreachable,
5105 },5124 },
5106 else => unreachable,5125 else => unreachable,
...@@ -5387,6 +5406,7 @@ pub const Type = struct {...@@ -5387,6 +5406,7 @@ pub const Type = struct {
5387 .ip_index = .const_slice_u8_sentinel_0_type,5406 .ip_index = .const_slice_u8_sentinel_0_type,
5388 .legacy = undefined,5407 .legacy = undefined,
5389 };5408 };
5409 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type, .legacy = undefined };
53905410
5391 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type, .legacy = undefined };5411 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 {...@@ -36,7 +36,6 @@ pub const Value = struct {
36 /// The only possible value for a particular type, which is stored externally.36 /// The only possible value for a particular type, which is stored externally.
37 the_only_possible_value,37 the_only_possible_value,
3838
39 empty_struct_value,
40 empty_array, // See last_no_payload_tag below.39 empty_array, // See last_no_payload_tag below.
41 // After this, the tag requires a payload.40 // After this, the tag requires a payload.
4241
...@@ -124,7 +123,6 @@ pub const Value = struct {...@@ -124,7 +123,6 @@ pub const Value = struct {
124 pub fn Type(comptime t: Tag) type {123 pub fn Type(comptime t: Tag) type {
125 return switch (t) {124 return switch (t) {
126 .the_only_possible_value,125 .the_only_possible_value,
127 .empty_struct_value,
128 .empty_array,126 .empty_array,
129 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),127 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
130128
...@@ -269,7 +267,6 @@ pub const Value = struct {...@@ -269,7 +267,6 @@ pub const Value = struct {
269 } else switch (self.legacy.ptr_otherwise.tag) {267 } else switch (self.legacy.ptr_otherwise.tag) {
270 .the_only_possible_value,268 .the_only_possible_value,
271 .empty_array,269 .empty_array,
272 .empty_struct_value,
273 => unreachable,270 => unreachable,
274271
275 .ty, .lazy_align, .lazy_size => {272 .ty, .lazy_align, .lazy_size => {
...@@ -488,7 +485,6 @@ pub const Value = struct {...@@ -488,7 +485,6 @@ pub const Value = struct {
488 }485 }
489 var val = start_val;486 var val = start_val;
490 while (true) switch (val.tag()) {487 while (true) switch (val.tag()) {
491 .empty_struct_value => return out_stream.writeAll("struct {}{}"),
492 .aggregate => {488 .aggregate => {
493 return out_stream.writeAll("(aggregate)");489 return out_stream.writeAll("(aggregate)");
494 },490 },
...@@ -1914,7 +1910,7 @@ pub const Value = struct {...@@ -1914,7 +1910,7 @@ pub const Value = struct {
1914 const a_tag = a.tag();1910 const a_tag = a.tag();
1915 const b_tag = b.tag();1911 const b_tag = b.tag();
1916 if (a_tag == b_tag) switch (a_tag) {1912 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,
1918 .enum_literal => {1914 .enum_literal => {
1919 const a_name = a.castTag(.enum_literal).?.data;1915 const a_name = a.castTag(.enum_literal).?.data;
1920 const b_name = b.castTag(.enum_literal).?.data;1916 const b_name = b.castTag(.enum_literal).?.data;
...@@ -2106,7 +2102,6 @@ pub const Value = struct {...@@ -2106,7 +2102,6 @@ pub const Value = struct {
2106 },2102 },
2107 .Struct => {2103 .Struct => {
2108 // A struct can be represented with one of:2104 // A struct can be represented with one of:
2109 // .empty_struct_value,
2110 // .the_one_possible_value,2105 // .the_one_possible_value,
2111 // .aggregate,2106 // .aggregate,
2112 // Note that we already checked above for matching tags, e.g. both .aggregate.2107 // Note that we already checked above for matching tags, e.g. both .aggregate.
...@@ -2254,7 +2249,6 @@ pub const Value = struct {...@@ -2254,7 +2249,6 @@ pub const Value = struct {
2254 },2249 },
2255 .Struct => {2250 .Struct => {
2256 switch (val.tag()) {2251 switch (val.tag()) {
2257 .empty_struct_value => {},
2258 .aggregate => {2252 .aggregate => {
2259 const field_values = val.castTag(.aggregate).?.data;2253 const field_values = val.castTag(.aggregate).?.data;
2260 for (field_values, 0..) |field_val, i| {2254 for (field_values, 0..) |field_val, i| {
...@@ -2587,7 +2581,6 @@ pub const Value = struct {...@@ -2587,7 +2581,6 @@ pub const Value = struct {
2587 .none => switch (val.tag()) {2581 .none => switch (val.tag()) {
2588 // This is the case of accessing an element of an undef array.2582 // This is the case of accessing an element of an undef array.
2589 .empty_array => unreachable, // out of bounds array index2583 .empty_array => unreachable, // out of bounds array index
2590 .empty_struct_value => unreachable, // out of bounds array index
25912584
2592 .empty_array_sentinel => {2585 .empty_array_sentinel => {
2593 assert(index == 0); // The only valid index for an empty array with sentinel.2586 assert(index == 0); // The only valid index for an empty array with sentinel.
...@@ -2749,6 +2742,17 @@ pub const Value = struct {...@@ -2749,6 +2742,17 @@ pub const Value = struct {
2749 pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {2742 pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {
2750 switch (val.ip_index) {2743 switch (val.ip_index) {
2751 .undef => return Value.undef,2744 .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
2752 .none => switch (val.tag()) {2756 .none => switch (val.tag()) {
2753 .aggregate => {2757 .aggregate => {
2754 const field_values = val.castTag(.aggregate).?.data;2758 const field_values = val.castTag(.aggregate).?.data;
...@@ -2762,17 +2766,6 @@ pub const Value = struct {...@@ -2762,17 +2766,6 @@ pub const Value = struct {
27622766
2763 .the_only_possible_value => return (try ty.onePossibleValue(mod)).?,2767 .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
2776 else => unreachable,2769 else => unreachable,
2777 },2770 },
2778 else => unreachable,2771 else => unreachable,
...@@ -5189,6 +5182,7 @@ pub const Value = struct {...@@ -5189,6 +5182,7 @@ pub const Value = struct {
51895182
5190 pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };5183 pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };
5191 pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined };5184 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
5193 pub fn makeBool(x: bool) Value {5187 pub fn makeBool(x: bool) Value {
5194 return if (x) Value.true else Value.false;5188 return if (x) Value.true else Value.false;