authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-03 20:22:05-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-20 14:02:08-04:00
logad3e0e4eb4afc3f633f5f8f04affc3e9ff886cb6
treee4fb117e0cb673ee4dbea06621d9e284882a8721
parent3c4b58cea76e51da1b79dee9e6c0a5cd2627a283

Sema: optimize typeHasOnePossibleValue


4 files changed, 322 insertions(+), 209 deletions(-)

src/Air.zig+3
...@@ -850,6 +850,8 @@ pub const Inst = struct {...@@ -850,6 +850,8 @@ pub const Inst = struct {
850 pub const Index = u32;850 pub const Index = u32;
851851
852 pub const Ref = enum(u32) {852 pub const Ref = enum(u32) {
853 u0_type = @intFromEnum(InternPool.Index.u0_type),
854 i0_type = @intFromEnum(InternPool.Index.i0_type),
853 u1_type = @intFromEnum(InternPool.Index.u1_type),855 u1_type = @intFromEnum(InternPool.Index.u1_type),
854 u8_type = @intFromEnum(InternPool.Index.u8_type),856 u8_type = @intFromEnum(InternPool.Index.u8_type),
855 i8_type = @intFromEnum(InternPool.Index.i8_type),857 i8_type = @intFromEnum(InternPool.Index.i8_type),
...@@ -909,6 +911,7 @@ pub const Inst = struct {...@@ -909,6 +911,7 @@ pub const Inst = struct {
909 single_const_pointer_to_comptime_int_type = @intFromEnum(InternPool.Index.single_const_pointer_to_comptime_int_type),911 single_const_pointer_to_comptime_int_type = @intFromEnum(InternPool.Index.single_const_pointer_to_comptime_int_type),
910 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),912 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),
911 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),913 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
914 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
912 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),915 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
913 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),916 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
914 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),917 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
src/InternPool.zig+30-6
...@@ -1243,11 +1243,13 @@ pub const Item = struct {...@@ -1243,11 +1243,13 @@ pub const Item = struct {
1243/// When adding a tag to this enum, consider adding a corresponding entry to1243/// When adding a tag to this enum, consider adding a corresponding entry to
1244/// `primitives` in AstGen.zig.1244/// `primitives` in AstGen.zig.
1245pub const Index = enum(u32) {1245pub const Index = enum(u32) {
1246 pub const first_type: Index = .u1_type;1246 pub const first_type: Index = .u0_type;
1247 pub const last_type: Index = .empty_struct_type;1247 pub const last_type: Index = .empty_struct_type;
1248 pub const first_value: Index = .undef;1248 pub const first_value: Index = .undef;
1249 pub const last_value: Index = .empty_struct;1249 pub const last_value: Index = .empty_struct;
12501250
1251 u0_type,
1252 i0_type,
1251 u1_type,1253 u1_type,
1252 u8_type,1254 u8_type,
1253 i8_type,1255 i8_type,
...@@ -1307,6 +1309,7 @@ pub const Index = enum(u32) {...@@ -1307,6 +1309,7 @@ pub const Index = enum(u32) {
1307 single_const_pointer_to_comptime_int_type,1309 single_const_pointer_to_comptime_int_type,
1308 slice_const_u8_type,1310 slice_const_u8_type,
1309 slice_const_u8_sentinel_0_type,1311 slice_const_u8_sentinel_0_type,
1312 optional_noreturn_type,
1310 anyerror_void_error_union_type,1313 anyerror_void_error_union_type,
1311 generic_poison_type,1314 generic_poison_type,
1312 /// `@TypeOf(.{})`1315 /// `@TypeOf(.{})`
...@@ -1533,6 +1536,16 @@ pub const Index = enum(u32) {...@@ -1533,6 +1536,16 @@ pub const Index = enum(u32) {
1533};1536};
15341537
1535pub const static_keys = [_]Key{1538pub const static_keys = [_]Key{
1539 .{ .int_type = .{
1540 .signedness = .unsigned,
1541 .bits = 0,
1542 } },
1543
1544 .{ .int_type = .{
1545 .signedness = .signed,
1546 .bits = 0,
1547 } },
1548
1536 .{ .int_type = .{1549 .{ .int_type = .{
1537 .signedness = .unsigned,1550 .signedness = .unsigned,
1538 .bits = 1,1551 .bits = 1,
...@@ -1639,6 +1652,7 @@ pub const static_keys = [_]Key{...@@ -1639,6 +1652,7 @@ pub const static_keys = [_]Key{
1639 .{ .simple_type = .extern_options },1652 .{ .simple_type = .extern_options },
1640 .{ .simple_type = .type_info },1653 .{ .simple_type = .type_info },
16411654
1655 // [*]u8
1642 .{ .ptr_type = .{1656 .{ .ptr_type = .{
1643 .child = .u8_type,1657 .child = .u8_type,
1644 .flags = .{1658 .flags = .{
...@@ -1646,7 +1660,7 @@ pub const static_keys = [_]Key{...@@ -1646,7 +1660,7 @@ pub const static_keys = [_]Key{
1646 },1660 },
1647 } },1661 } },
16481662
1649 // manyptr_const_u8_type1663 // [*]const u8
1650 .{ .ptr_type = .{1664 .{ .ptr_type = .{
1651 .child = .u8_type,1665 .child = .u8_type,
1652 .flags = .{1666 .flags = .{
...@@ -1655,7 +1669,7 @@ pub const static_keys = [_]Key{...@@ -1655,7 +1669,7 @@ pub const static_keys = [_]Key{
1655 },1669 },
1656 } },1670 } },
16571671
1658 // manyptr_const_u8_sentinel_0_type1672 // [*:0]const u8
1659 .{ .ptr_type = .{1673 .{ .ptr_type = .{
1660 .child = .u8_type,1674 .child = .u8_type,
1661 .sentinel = .zero_u8,1675 .sentinel = .zero_u8,
...@@ -1665,6 +1679,7 @@ pub const static_keys = [_]Key{...@@ -1665,6 +1679,7 @@ pub const static_keys = [_]Key{
1665 },1679 },
1666 } },1680 } },
16671681
1682 // comptime_int
1668 .{ .ptr_type = .{1683 .{ .ptr_type = .{
1669 .child = .comptime_int_type,1684 .child = .comptime_int_type,
1670 .flags = .{1685 .flags = .{
...@@ -1673,7 +1688,7 @@ pub const static_keys = [_]Key{...@@ -1673,7 +1688,7 @@ pub const static_keys = [_]Key{
1673 },1688 },
1674 } },1689 } },
16751690
1676 // slice_const_u8_type1691 // []const u8
1677 .{ .ptr_type = .{1692 .{ .ptr_type = .{
1678 .child = .u8_type,1693 .child = .u8_type,
1679 .flags = .{1694 .flags = .{
...@@ -1682,7 +1697,7 @@ pub const static_keys = [_]Key{...@@ -1682,7 +1697,7 @@ pub const static_keys = [_]Key{
1682 },1697 },
1683 } },1698 } },
16841699
1685 // slice_const_u8_sentinel_0_type1700 // [:0]const u8
1686 .{ .ptr_type = .{1701 .{ .ptr_type = .{
1687 .child = .u8_type,1702 .child = .u8_type,
1688 .sentinel = .zero_u8,1703 .sentinel = .zero_u8,
...@@ -1692,7 +1707,10 @@ pub const static_keys = [_]Key{...@@ -1692,7 +1707,10 @@ pub const static_keys = [_]Key{
1692 },1707 },
1693 } },1708 } },
16941709
1695 // anyerror_void_error_union_type1710 // ?noreturn
1711 .{ .opt_type = .noreturn_type },
1712
1713 // anyerror!void
1696 .{ .error_union_type = .{1714 .{ .error_union_type = .{
1697 .error_set_type = .anyerror_type,1715 .error_set_type = .anyerror_type,
1698 .payload_type = .void_type,1716 .payload_type = .void_type,
...@@ -5465,6 +5483,8 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -5465,6 +5483,8 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5465 // An alternative would be to topological sort the static keys, but this would5483 // An alternative would be to topological sort the static keys, but this would
5466 // mean that the range of type indices would not be dense.5484 // mean that the range of type indices would not be dense.
5467 return switch (index) {5485 return switch (index) {
5486 .u0_type,
5487 .i0_type,
5468 .u1_type,5488 .u1_type,
5469 .u8_type,5489 .u8_type,
5470 .i8_type,5490 .i8_type,
...@@ -5524,6 +5544,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -5524,6 +5544,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5524 .single_const_pointer_to_comptime_int_type,5544 .single_const_pointer_to_comptime_int_type,
5525 .slice_const_u8_type,5545 .slice_const_u8_type,
5526 .slice_const_u8_sentinel_0_type,5546 .slice_const_u8_sentinel_0_type,
5547 .optional_noreturn_type,
5527 .anyerror_void_error_union_type,5548 .anyerror_void_error_union_type,
5528 .generic_poison_type,5549 .generic_poison_type,
5529 .empty_struct_type,5550 .empty_struct_type,
...@@ -5685,6 +5706,8 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {...@@ -5685,6 +5706,8 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
5685/// rather than the more straightforward implementation of calling `indexToKey`.5706/// rather than the more straightforward implementation of calling `indexToKey`.
5686pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {5707pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
5687 return switch (index) {5708 return switch (index) {
5709 .u0_type,
5710 .i0_type,
5688 .u1_type,5711 .u1_type,
5689 .u8_type,5712 .u8_type,
5690 .i8_type,5713 .i8_type,
...@@ -5756,6 +5779,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5756,6 +5779,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
5756 .slice_const_u8_sentinel_0_type,5779 .slice_const_u8_sentinel_0_type,
5757 => .Pointer,5780 => .Pointer,
57585781
5782 .optional_noreturn_type => .Optional,
5759 .anyerror_void_error_union_type => .ErrorUnion,5783 .anyerror_void_error_union_type => .ErrorUnion,
5760 .empty_struct_type => .Struct,5784 .empty_struct_type => .Struct,
57615785
src/Sema.zig+286-203
...@@ -33749,6 +33749,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -33749,6 +33749,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3374933749
33750 .none => unreachable,33750 .none => unreachable,
3375133751
33752 .u0_type,
33753 .i0_type,
33752 .u1_type,33754 .u1_type,
33753 .u8_type,33755 .u8_type,
33754 .i8_type,33756 .i8_type,
...@@ -33797,6 +33799,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -33797,6 +33799,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
33797 .single_const_pointer_to_comptime_int_type,33799 .single_const_pointer_to_comptime_int_type,
33798 .slice_const_u8_type,33800 .slice_const_u8_type,
33799 .slice_const_u8_sentinel_0_type,33801 .slice_const_u8_sentinel_0_type,
33802 .optional_noreturn_type,
33800 .anyerror_void_error_union_type,33803 .anyerror_void_error_union_type,
33801 .generic_poison_type,33804 .generic_poison_type,
33802 .empty_struct_type,33805 .empty_struct_type,
...@@ -34935,231 +34938,311 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -34935,231 +34938,311 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
34935pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {34938pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
34936 const mod = sema.mod;34939 const mod = sema.mod;
34937 return switch (ty.toIntern()) {34940 return switch (ty.toIntern()) {
34941 .u0_type,
34942 .i0_type,
34943 => try mod.intValue(ty, 0),
34944 .u1_type,
34945 .u8_type,
34946 .i8_type,
34947 .u16_type,
34948 .i16_type,
34949 .u29_type,
34950 .u32_type,
34951 .i32_type,
34952 .u64_type,
34953 .i64_type,
34954 .u80_type,
34955 .u128_type,
34956 .i128_type,
34957 .usize_type,
34958 .isize_type,
34959 .c_char_type,
34960 .c_short_type,
34961 .c_ushort_type,
34962 .c_int_type,
34963 .c_uint_type,
34964 .c_long_type,
34965 .c_ulong_type,
34966 .c_longlong_type,
34967 .c_ulonglong_type,
34968 .c_longdouble_type,
34969 .f16_type,
34970 .f32_type,
34971 .f64_type,
34972 .f80_type,
34973 .f128_type,
34974 .anyopaque_type,
34975 .bool_type,
34976 .type_type,
34977 .anyerror_type,
34978 .comptime_int_type,
34979 .comptime_float_type,
34980 .enum_literal_type,
34981 .atomic_order_type,
34982 .atomic_rmw_op_type,
34983 .calling_convention_type,
34984 .address_space_type,
34985 .float_mode_type,
34986 .reduce_op_type,
34987 .call_modifier_type,
34988 .prefetch_options_type,
34989 .export_options_type,
34990 .extern_options_type,
34991 .type_info_type,
34992 .manyptr_u8_type,
34993 .manyptr_const_u8_type,
34994 .manyptr_const_u8_sentinel_0_type,
34995 .single_const_pointer_to_comptime_int_type,
34996 .slice_const_u8_type,
34997 .slice_const_u8_sentinel_0_type,
34998 .anyerror_void_error_union_type,
34999 => null,
35000 .void_type => Value.void,
35001 .noreturn_type => Value.@"unreachable",
35002 .anyframe_type => unreachable,
35003 .null_type => Value.null,
35004 .undefined_type => Value.undef,
35005 .optional_noreturn_type => try mod.nullValue(ty),
35006 .generic_poison_type => error.GenericPoison,
34938 .empty_struct_type => Value.empty_struct,35007 .empty_struct_type => Value.empty_struct,
34939 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {35008 // values, not types
34940 .int_type => |int_type| {35009 .undef,
34941 if (int_type.bits == 0) {35010 .zero,
34942 return try mod.intValue(ty, 0);35011 .zero_usize,
34943 } else {35012 .zero_u8,
34944 return null;35013 .one,
34945 }35014 .one_usize,
34946 },35015 .one_u8,
3494735016 .four_u8,
34948 .ptr_type,35017 .negative_one,
34949 .error_union_type,35018 .calling_convention_c,
34950 .func_type,35019 .calling_convention_inline,
34951 .anyframe_type,35020 .void_value,
34952 .error_set_type,35021 .unreachable_value,
34953 .inferred_error_set_type,35022 .null_value,
35023 .bool_true,
35024 .bool_false,
35025 .empty_struct,
35026 .generic_poison,
35027 // invalid
35028 .var_args_param_type,
35029 .none,
35030 => unreachable,
35031 _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
35032 .type_int_signed, // i0 handled above
35033 .type_int_unsigned, // u0 handled above
35034 .type_pointer,
35035 .type_slice,
35036 .type_optional, // ?noreturn handled above
35037 .type_anyframe,
35038 .type_error_union,
35039 .type_error_set,
35040 .type_inferred_error_set,
35041 .type_opaque,
35042 .type_function,
34954 => null,35043 => null,
3495535044 .simple_type, // handled above
34956 inline .array_type, .vector_type => |seq_type, seq_tag| {35045 // values, not types
34957 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;35046 .undef,
34958 if (seq_type.len + @intFromBool(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{35047 .runtime_value,
34959 .ty = ty.toIntern(),35048 .simple_value,
34960 .storage = .{ .elems = &.{} },35049 .ptr_decl,
34961 } })).toValue();35050 .ptr_mut_decl,
3496235051 .ptr_comptime_field,
34963 if (try sema.typeHasOnePossibleValue(seq_type.child.toType())) |opv| {35052 .ptr_int,
34964 return (try mod.intern(.{ .aggregate = .{35053 .ptr_eu_payload,
35054 .ptr_opt_payload,
35055 .ptr_elem,
35056 .ptr_field,
35057 .ptr_slice,
35058 .opt_payload,
35059 .opt_null,
35060 .int_u8,
35061 .int_u16,
35062 .int_u32,
35063 .int_i32,
35064 .int_usize,
35065 .int_comptime_int_u32,
35066 .int_comptime_int_i32,
35067 .int_small,
35068 .int_positive,
35069 .int_negative,
35070 .int_lazy_align,
35071 .int_lazy_size,
35072 .error_set_error,
35073 .error_union_error,
35074 .error_union_payload,
35075 .enum_literal,
35076 .enum_tag,
35077 .float_f16,
35078 .float_f32,
35079 .float_f64,
35080 .float_f80,
35081 .float_f128,
35082 .float_c_longdouble_f80,
35083 .float_c_longdouble_f128,
35084 .float_comptime_float,
35085 .variable,
35086 .extern_func,
35087 .func,
35088 .only_possible_value,
35089 .union_value,
35090 .bytes,
35091 .aggregate,
35092 .repeated,
35093 // memoized value, not types
35094 .memoized_call,
35095 => unreachable,
35096 .type_array_big,
35097 .type_array_small,
35098 .type_vector,
35099 .type_enum_auto,
35100 .type_enum_explicit,
35101 .type_enum_nonexhaustive,
35102 .type_struct,
35103 .type_struct_ns,
35104 .type_struct_anon,
35105 .type_tuple_anon,
35106 .type_union_tagged,
35107 .type_union_untagged,
35108 .type_union_safety,
35109 => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
35110 inline .array_type, .vector_type => |seq_type, seq_tag| {
35111 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
35112 if (seq_type.len + @intFromBool(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{
34965 .ty = ty.toIntern(),35113 .ty = ty.toIntern(),
34966 .storage = .{ .repeated_elem = opv.toIntern() },35114 .storage = .{ .elems = &.{} },
34967 } })).toValue();35115 } })).toValue();
34968 }
34969 return null;
34970 },
34971 .opt_type => |child| {
34972 if (child == .noreturn_type) {
34973 return try mod.nullValue(ty);
34974 } else {
34975 return null;
34976 }
34977 },
3497835116
34979 .simple_type => |t| switch (t) {35117 if (try sema.typeHasOnePossibleValue(seq_type.child.toType())) |opv| {
34980 .f16,35118 return (try mod.intern(.{ .aggregate = .{
34981 .f32,35119 .ty = ty.toIntern(),
34982 .f64,35120 .storage = .{ .repeated_elem = opv.toIntern() },
34983 .f80,35121 } })).toValue();
34984 .f128,35122 }
34985 .usize,35123 return null;
34986 .isize,35124 },
34987 .c_char,
34988 .c_short,
34989 .c_ushort,
34990 .c_int,
34991 .c_uint,
34992 .c_long,
34993 .c_ulong,
34994 .c_longlong,
34995 .c_ulonglong,
34996 .c_longdouble,
34997 .anyopaque,
34998 .bool,
34999 .type,
35000 .anyerror,
35001 .comptime_int,
35002 .comptime_float,
35003 .enum_literal,
35004 .atomic_order,
35005 .atomic_rmw_op,
35006 .calling_convention,
35007 .address_space,
35008 .float_mode,
35009 .reduce_op,
35010 .call_modifier,
35011 .prefetch_options,
35012 .export_options,
35013 .extern_options,
35014 .type_info,
35015 => null,
35016
35017 .void => Value.void,
35018 .noreturn => Value.@"unreachable",
35019 .null => Value.null,
35020 .undefined => Value.undef,
3502135125
35022 .generic_poison => return error.GenericPoison,35126 .struct_type => |struct_type| {
35023 },35127 const resolved_ty = try sema.resolveTypeFields(ty);
35024 .struct_type => |struct_type| {35128 if (mod.structPtrUnwrap(struct_type.index)) |s| {
35025 const resolved_ty = try sema.resolveTypeFields(ty);35129 const field_vals = try sema.arena.alloc(InternPool.Index, s.fields.count());
35026 if (mod.structPtrUnwrap(struct_type.index)) |s| {35130 for (field_vals, s.fields.values(), 0..) |*field_val, field, i| {
35027 const field_vals = try sema.arena.alloc(InternPool.Index, s.fields.count());35131 if (field.is_comptime) {
35028 for (field_vals, s.fields.values(), 0..) |*field_val, field, i| {35132 field_val.* = field.default_val;
35029 if (field.is_comptime) {35133 continue;
35030 field_val.* = field.default_val;35134 }
35031 continue;35135 if (field.ty.eql(resolved_ty, sema.mod)) {
35032 }35136 const msg = try Module.ErrorMsg.create(
35033 if (field.ty.eql(resolved_ty, sema.mod)) {35137 sema.gpa,
35034 const msg = try Module.ErrorMsg.create(35138 s.srcLoc(sema.mod),
35035 sema.gpa,35139 "struct '{}' depends on itself",
35036 s.srcLoc(sema.mod),35140 .{ty.fmt(sema.mod)},
35037 "struct '{}' depends on itself",35141 );
35038 .{ty.fmt(sema.mod)},35142 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
35039 );35143 return sema.failWithOwnedErrorMsg(msg);
35040 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});35144 }
35041 return sema.failWithOwnedErrorMsg(msg);35145 if (try sema.typeHasOnePossibleValue(field.ty)) |field_opv| {
35146 field_val.* = try field_opv.intern(field.ty, mod);
35147 } else return null;
35042 }35148 }
35043 if (try sema.typeHasOnePossibleValue(field.ty)) |field_opv| {35149
35044 field_val.* = try field_opv.intern(field.ty, mod);35150 // In this case the struct has no runtime-known fields and
35045 } else return null;35151 // therefore has one possible value.
35152 return (try mod.intern(.{ .aggregate = .{
35153 .ty = ty.toIntern(),
35154 .storage = .{ .elems = field_vals },
35155 } })).toValue();
35046 }35156 }
3504735157
35048 // In this case the struct has no runtime-known fields and35158 // In this case the struct has no fields at all and
35049 // therefore has one possible value.35159 // therefore has one possible value.
35050 return (try mod.intern(.{ .aggregate = .{35160 return (try mod.intern(.{ .aggregate = .{
35051 .ty = ty.toIntern(),35161 .ty = ty.toIntern(),
35052 .storage = .{ .elems = field_vals },35162 .storage = .{ .elems = &.{} },
35053 } })).toValue();35163 } })).toValue();
35054 }35164 },
35055
35056 // In this case the struct has no fields at all and
35057 // therefore has one possible value.
35058 return (try mod.intern(.{ .aggregate = .{
35059 .ty = ty.toIntern(),
35060 .storage = .{ .elems = &.{} },
35061 } })).toValue();
35062 },
35063
35064 .anon_struct_type => |tuple| {
35065 for (tuple.values) |val| {
35066 if (val == .none) return null;
35067 }
35068 // In this case the struct has all comptime-known fields and
35069 // therefore has one possible value.
35070 // TODO: write something like getCoercedInts to avoid needing to dupe
35071 return (try mod.intern(.{ .aggregate = .{
35072 .ty = ty.toIntern(),
35073 .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values) },
35074 } })).toValue();
35075 },
3507635165
35077 .union_type => |union_type| {35166 .anon_struct_type => |tuple| {
35078 const resolved_ty = try sema.resolveTypeFields(ty);35167 for (tuple.values) |val| {
35079 const union_obj = mod.unionPtr(union_type.index);35168 if (val == .none) return null;
35080 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse35169 }
35081 return null;35170 // In this case the struct has all comptime-known fields and
35082 const fields = union_obj.fields.values();35171 // therefore has one possible value.
35083 if (fields.len == 0) {35172 // TODO: write something like getCoercedInts to avoid needing to dupe
35084 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });35173 return (try mod.intern(.{ .aggregate = .{
35085 return only.toValue();35174 .ty = ty.toIntern(),
35086 }35175 .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values) },
35087 const only_field = fields[0];35176 } })).toValue();
35088 if (only_field.ty.eql(resolved_ty, sema.mod)) {35177 },
35089 const msg = try Module.ErrorMsg.create(
35090 sema.gpa,
35091 union_obj.srcLoc(sema.mod),
35092 "union '{}' depends on itself",
35093 .{ty.fmt(sema.mod)},
35094 );
35095 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
35096 return sema.failWithOwnedErrorMsg(msg);
35097 }
35098 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
35099 return null;
35100 const only = try mod.intern(.{ .un = .{
35101 .ty = resolved_ty.toIntern(),
35102 .tag = tag_val.toIntern(),
35103 .val = val_val.toIntern(),
35104 } });
35105 return only.toValue();
35106 },
35107 .opaque_type => null,
35108 .enum_type => |enum_type| switch (enum_type.tag_mode) {
35109 .nonexhaustive => {
35110 if (enum_type.tag_ty == .comptime_int_type) return null;
3511135178
35112 if (try sema.typeHasOnePossibleValue(enum_type.tag_ty.toType())) |int_opv| {35179 .union_type => |union_type| {
35113 const only = try mod.intern(.{ .enum_tag = .{35180 const resolved_ty = try sema.resolveTypeFields(ty);
35114 .ty = ty.toIntern(),35181 const union_obj = mod.unionPtr(union_type.index);
35115 .int = int_opv.toIntern(),35182 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse
35116 } });35183 return null;
35184 const fields = union_obj.fields.values();
35185 if (fields.len == 0) {
35186 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
35117 return only.toValue();35187 return only.toValue();
35118 }35188 }
3511935189 const only_field = fields[0];
35120 return null;35190 if (only_field.ty.eql(resolved_ty, sema.mod)) {
35191 const msg = try Module.ErrorMsg.create(
35192 sema.gpa,
35193 union_obj.srcLoc(sema.mod),
35194 "union '{}' depends on itself",
35195 .{ty.fmt(sema.mod)},
35196 );
35197 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
35198 return sema.failWithOwnedErrorMsg(msg);
35199 }
35200 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
35201 return null;
35202 const only = try mod.intern(.{ .un = .{
35203 .ty = resolved_ty.toIntern(),
35204 .tag = tag_val.toIntern(),
35205 .val = val_val.toIntern(),
35206 } });
35207 return only.toValue();
35121 },35208 },
35122 .auto, .explicit => {
35123 if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
3512435209
35125 switch (enum_type.names.len) {35210 .enum_type => |enum_type| switch (enum_type.tag_mode) {
35126 0 => {35211 .nonexhaustive => {
35127 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });35212 if (enum_type.tag_ty == .comptime_int_type) return null;
35213
35214 if (try sema.typeHasOnePossibleValue(enum_type.tag_ty.toType())) |int_opv| {
35215 const only = try mod.intern(.{ .enum_tag = .{
35216 .ty = ty.toIntern(),
35217 .int = int_opv.toIntern(),
35218 } });
35128 return only.toValue();35219 return only.toValue();
35129 },35220 }
35130 1 => return try mod.getCoerced((if (enum_type.values.len == 0)35221
35131 try mod.intern(.{ .int = .{35222 return null;
35132 .ty = enum_type.tag_ty,35223 },
35133 .storage = .{ .u64 = 0 },35224 .auto, .explicit => {
35134 } })35225 if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
35135 else35226
35136 enum_type.values[0]).toValue(), ty),35227 switch (enum_type.names.len) {
35137 else => return null,35228 0 => {
35138 }35229 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
35230 return only.toValue();
35231 },
35232 1 => return try mod.getCoerced((if (enum_type.values.len == 0)
35233 try mod.intern(.{ .int = .{
35234 .ty = enum_type.tag_ty,
35235 .storage = .{ .u64 = 0 },
35236 } })
35237 else
35238 enum_type.values[0]).toValue(), ty),
35239 else => return null,
35240 }
35241 },
35139 },35242 },
35140 },
3514135243
35142 // values, not types35244 else => unreachable,
35143 .undef,35245 },
35144 .runtime_value,
35145 .simple_value,
35146 .variable,
35147 .extern_func,
35148 .func,
35149 .int,
35150 .err,
35151 .error_union,
35152 .enum_literal,
35153 .enum_tag,
35154 .empty_enum_value,
35155 .float,
35156 .ptr,
35157 .opt,
35158 .aggregate,
35159 .un,
35160 // memoization, not types
35161 .memoized_call,
35162 => unreachable,
35163 },35246 },
35164 };35247 };
35165}35248}
src/Zir.zig+3
...@@ -2005,6 +2005,8 @@ pub const Inst = struct {...@@ -2005,6 +2005,8 @@ pub const Inst = struct {
2005 /// The tag type is specified so that it is safe to bitcast between `[]u32`2005 /// The tag type is specified so that it is safe to bitcast between `[]u32`
2006 /// and `[]Ref`.2006 /// and `[]Ref`.
2007 pub const Ref = enum(u32) {2007 pub const Ref = enum(u32) {
2008 u0_type = @intFromEnum(InternPool.Index.u0_type),
2009 i0_type = @intFromEnum(InternPool.Index.i0_type),
2008 u1_type = @intFromEnum(InternPool.Index.u1_type),2010 u1_type = @intFromEnum(InternPool.Index.u1_type),
2009 u8_type = @intFromEnum(InternPool.Index.u8_type),2011 u8_type = @intFromEnum(InternPool.Index.u8_type),
2010 i8_type = @intFromEnum(InternPool.Index.i8_type),2012 i8_type = @intFromEnum(InternPool.Index.i8_type),
...@@ -2064,6 +2066,7 @@ pub const Inst = struct {...@@ -2064,6 +2066,7 @@ pub const Inst = struct {
2064 single_const_pointer_to_comptime_int_type = @intFromEnum(InternPool.Index.single_const_pointer_to_comptime_int_type),2066 single_const_pointer_to_comptime_int_type = @intFromEnum(InternPool.Index.single_const_pointer_to_comptime_int_type),
2065 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),2067 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),
2066 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),2068 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
2069 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
2067 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),2070 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
2068 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),2071 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
2069 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),2072 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),