Commit f21ca3da19

Andrew Kelley <andrew@ziglang.org>
2023-05-19 04:05:46
compiler: move `anyframe->T` to InternPool
Also I moved `anyframe` from being represented by `SimpleType` to being represented by the `none` tag of `anyframe_type` because most code wants to handle these two types together.
1 parent 1788216
src/InternPool.zig
@@ -132,6 +132,9 @@ pub const Key = union(enum) {
     array_type: ArrayType,
     vector_type: VectorType,
     opt_type: Index,
+    /// `anyframe->T`. The payload is the child type, which may be `none` to indicate
+    /// `anyframe`.
+    anyframe_type: Index,
     error_union_type: struct {
         error_set_type: Index,
         payload_type: Index,
@@ -503,6 +506,7 @@ pub const Key = union(enum) {
             .array_type,
             .vector_type,
             .opt_type,
+            .anyframe_type,
             .error_union_type,
             .simple_type,
             .simple_value,
@@ -597,7 +601,11 @@ pub const Key = union(enum) {
             },
             .opt_type => |a_info| {
                 const b_info = b.opt_type;
-                return std.meta.eql(a_info, b_info);
+                return a_info == b_info;
+            },
+            .anyframe_type => |a_info| {
+                const b_info = b.anyframe_type;
+                return a_info == b_info;
             },
             .error_union_type => |a_info| {
                 const b_info = b.error_union_type;
@@ -752,6 +760,7 @@ pub const Key = union(enum) {
             .array_type,
             .vector_type,
             .opt_type,
+            .anyframe_type,
             .error_union_type,
             .simple_type,
             .struct_type,
@@ -1037,7 +1046,7 @@ pub const static_keys = [_]Key{
     .{ .simple_type = .comptime_int },
     .{ .simple_type = .comptime_float },
     .{ .simple_type = .noreturn },
-    .{ .simple_type = .@"anyframe" },
+    .{ .anyframe_type = .none },
     .{ .simple_type = .null },
     .{ .simple_type = .undefined },
     .{ .simple_type = .enum_literal },
@@ -1203,6 +1212,10 @@ pub const Tag = enum(u8) {
     /// An optional type.
     /// data is the child type.
     type_optional,
+    /// The type `anyframe->T`.
+    /// data is the child type.
+    /// If the child type is `none`, the type is `anyframe`.
+    type_anyframe,
     /// An error union type.
     /// data is payload to ErrorUnion.
     type_error_union,
@@ -1421,7 +1434,6 @@ pub const SimpleType = enum(u32) {
     comptime_int,
     comptime_float,
     noreturn,
-    @"anyframe",
     null,
     undefined,
     enum_literal,
@@ -1781,6 +1793,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
         },
 
         .type_optional => .{ .opt_type = @intToEnum(Index, data) },
+        .type_anyframe => .{ .anyframe_type = @intToEnum(Index, data) },
 
         .type_error_union => @panic("TODO"),
 
@@ -2144,10 +2157,18 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
                 }),
             });
         },
-        .opt_type => |opt_type| {
+        .opt_type => |payload_type| {
+            assert(payload_type != .none);
             ip.items.appendAssumeCapacity(.{
                 .tag = .type_optional,
-                .data = @enumToInt(opt_type),
+                .data = @enumToInt(payload_type),
+            });
+        },
+        .anyframe_type => |payload_type| {
+            // payload_type might be none, indicating the type is `anyframe`.
+            ip.items.appendAssumeCapacity(.{
+                .tag = .type_anyframe,
+                .data = @enumToInt(payload_type),
             });
         },
         .error_union_type => |error_union_type| {
@@ -3063,7 +3084,7 @@ pub fn childType(ip: InternPool, i: Index) Index {
         .ptr_type => |ptr_type| ptr_type.elem_type,
         .vector_type => |vector_type| vector_type.child,
         .array_type => |array_type| array_type.child,
-        .opt_type => |child| child,
+        .opt_type, .anyframe_type => |child| child,
         else => unreachable,
     };
 }
@@ -3231,6 +3252,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
             .type_pointer => @sizeOf(Pointer),
             .type_slice => 0,
             .type_optional => 0,
+            .type_anyframe => 0,
             .type_error_union => @sizeOf(ErrorUnion),
             .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
             .type_enum_auto => @sizeOf(EnumAuto),
src/Module.zig
@@ -6869,6 +6869,12 @@ pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Typ
     return (try intern(mod, .{ .func_type = info })).toType();
 }
 
+/// Use this for `anyframe->T` only.
+/// For `anyframe`, use the `InternPool.Index.anyframe` tag directly.
+pub fn anyframeType(mod: *Module, payload_ty: Type) Allocator.Error!Type {
+    return (try intern(mod, .{ .anyframe_type = payload_ty.toIntern() })).toType();
+}
+
 /// Supports optionals in addition to pointers.
 pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
     if (ty.isPtrLikeOptional(mod)) {
src/Sema.zig
@@ -8042,9 +8042,10 @@ fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
     if (true) {
         return sema.failWithUseOfAsync(block, inst_data.src());
     }
+    const mod = sema.mod;
     const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node };
     const return_type = try sema.resolveType(block, operand_src, inst_data.operand);
-    const anyframe_type = try Type.Tag.anyframe_T.create(sema.arena, return_type);
+    const anyframe_type = try mod.anyframeType(return_type);
 
     return sema.addType(anyframe_type);
 }
@@ -31626,10 +31627,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
             },
 
             .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
-            .anyframe_T => {
-                const child_ty = ty.castTag(.anyframe_T).?.data;
-                return sema.resolveTypeRequiresComptime(child_ty);
-            },
         },
         else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
             .int_type => false,
@@ -31641,6 +31638,10 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
                     return sema.resolveTypeRequiresComptime(child_ty);
                 }
             },
+            .anyframe_type => |child| {
+                if (child == .none) return false;
+                return sema.resolveTypeRequiresComptime(child.toType());
+            },
             .array_type => |array_type| return sema.resolveTypeRequiresComptime(array_type.child.toType()),
             .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),
             .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),
@@ -31669,7 +31670,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
                 .bool,
                 .void,
                 .anyerror,
-                .@"anyframe",
                 .noreturn,
                 .generic_poison,
                 .var_args_param,
@@ -33054,7 +33054,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
             .error_set_merged,
             .error_union,
             .error_set_inferred,
-            .anyframe_T,
             .pointer,
             => return null,
 
@@ -33083,6 +33082,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
             .ptr_type,
             .error_union_type,
             .func_type,
+            .anyframe_type,
             => null,
 
             .array_type => |array_type| {
@@ -33130,7 +33130,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
                 .anyerror,
                 .comptime_int,
                 .comptime_float,
-                .@"anyframe",
                 .enum_literal,
                 .atomic_order,
                 .atomic_rmw_op,
@@ -33688,10 +33687,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
             },
 
             .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
-            .anyframe_T => {
-                const child_ty = ty.castTag(.anyframe_T).?.data;
-                return sema.typeRequiresComptime(child_ty);
-            },
         },
         else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
             .int_type => return false,
@@ -33703,6 +33698,10 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
                     return sema.typeRequiresComptime(child_ty);
                 }
             },
+            .anyframe_type => |child| {
+                if (child == .none) return false;
+                return sema.typeRequiresComptime(child.toType());
+            },
             .array_type => |array_type| return sema.typeRequiresComptime(array_type.child.toType()),
             .vector_type => |vector_type| return sema.typeRequiresComptime(vector_type.child.toType()),
             .opt_type => |child| return sema.typeRequiresComptime(child.toType()),
@@ -33733,7 +33732,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
                 .bool,
                 .void,
                 .anyerror,
-                .@"anyframe",
                 .noreturn,
                 .generic_poison,
                 .atomic_order,
src/type.zig
@@ -50,21 +50,20 @@ pub const Type = struct {
                 .optional => return .Optional,
 
                 .error_union => return .ErrorUnion,
-
-                .anyframe_T => return .AnyFrame,
             },
-            else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
-                .int_type => return .Int,
-                .ptr_type => return .Pointer,
-                .array_type => return .Array,
-                .vector_type => return .Vector,
-                .opt_type => return .Optional,
-                .error_union_type => return .ErrorUnion,
-                .struct_type, .anon_struct_type => return .Struct,
-                .union_type => return .Union,
-                .opaque_type => return .Opaque,
-                .enum_type => return .Enum,
-                .func_type => return .Fn,
+            else => return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
+                .int_type => .Int,
+                .ptr_type => .Pointer,
+                .array_type => .Array,
+                .vector_type => .Vector,
+                .opt_type => .Optional,
+                .error_union_type => .ErrorUnion,
+                .struct_type, .anon_struct_type => .Struct,
+                .union_type => .Union,
+                .opaque_type => .Opaque,
+                .enum_type => .Enum,
+                .func_type => .Fn,
+                .anyframe_type => .AnyFrame,
                 .simple_type => |s| switch (s) {
                     .f16,
                     .f32,
@@ -72,7 +71,7 @@ pub const Type = struct {
                     .f80,
                     .f128,
                     .c_longdouble,
-                    => return .Float,
+                    => .Float,
 
                     .usize,
                     .isize,
@@ -85,20 +84,19 @@ pub const Type = struct {
                     .c_ulong,
                     .c_longlong,
                     .c_ulonglong,
-                    => return .Int,
-
-                    .anyopaque => return .Opaque,
-                    .bool => return .Bool,
-                    .void => return .Void,
-                    .type => return .Type,
-                    .anyerror => return .ErrorSet,
-                    .comptime_int => return .ComptimeInt,
-                    .comptime_float => return .ComptimeFloat,
-                    .noreturn => return .NoReturn,
-                    .@"anyframe" => return .AnyFrame,
-                    .null => return .Null,
-                    .undefined => return .Undefined,
-                    .enum_literal => return .EnumLiteral,
+                    => .Int,
+
+                    .anyopaque => .Opaque,
+                    .bool => .Bool,
+                    .void => .Void,
+                    .type => .Type,
+                    .anyerror => .ErrorSet,
+                    .comptime_int => .ComptimeInt,
+                    .comptime_float => .ComptimeFloat,
+                    .noreturn => .NoReturn,
+                    .null => .Null,
+                    .undefined => .Undefined,
+                    .enum_literal => .EnumLiteral,
 
                     .atomic_order,
                     .atomic_rmw_op,
@@ -107,14 +105,14 @@ pub const Type = struct {
                     .float_mode,
                     .reduce_op,
                     .call_modifier,
-                    => return .Enum,
+                    => .Enum,
 
                     .prefetch_options,
                     .export_options,
                     .extern_options,
-                    => return .Struct,
+                    => .Struct,
 
-                    .type_info => return .Union,
+                    .type_info => .Union,
 
                     .generic_poison => return error.GenericPoison,
                     .var_args_param => unreachable,
@@ -408,11 +406,6 @@ pub const Type = struct {
 
                 return true;
             },
-
-            .anyframe_T => {
-                if (b.zigTypeTag(mod) != .AnyFrame) return false;
-                return a.elemType2(mod).eql(b.elemType2(mod), mod);
-            },
         }
     }
 
@@ -488,11 +481,6 @@ pub const Type = struct {
                 const payload_ty = ty.errorUnionPayload();
                 hashWithHasher(payload_ty, hasher, mod);
             },
-
-            .anyframe_T => {
-                std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame);
-                hashWithHasher(ty.childType(mod), hasher, mod);
-            },
         }
     }
 
@@ -542,9 +530,7 @@ pub const Type = struct {
             .inferred_alloc_mut,
             => unreachable,
 
-            .optional,
-            .anyframe_T,
-            => {
+            .optional => {
                 const payload = self.cast(Payload.ElemType).?;
                 const new_payload = try allocator.create(Payload.ElemType);
                 new_payload.* = .{
@@ -668,12 +654,6 @@ pub const Type = struct {
         while (true) {
             const t = ty.tag();
             switch (t) {
-                .anyframe_T => {
-                    const return_type = ty.castTag(.anyframe_T).?.data;
-                    try writer.print("anyframe->", .{});
-                    ty = return_type;
-                    continue;
-                },
                 .optional => {
                     const child_type = ty.castTag(.optional).?.data;
                     try writer.writeByte('?');
@@ -838,11 +818,6 @@ pub const Type = struct {
                     try writer.writeByte('?');
                     try print(child_type, writer, mod);
                 },
-                .anyframe_T => {
-                    const return_type = ty.castTag(.anyframe_T).?.data;
-                    try writer.print("anyframe->", .{});
-                    try print(return_type, writer, mod);
-                },
                 .error_set => {
                     const names = ty.castTag(.error_set).?.data.names.keys();
                     try writer.writeAll("error{");
@@ -1034,6 +1009,11 @@ pub const Type = struct {
                         try print(fn_info.return_type.toType(), writer, mod);
                     }
                 },
+                .anyframe_type => |child| {
+                    if (child == .none) return writer.writeAll("anyframe");
+                    try writer.writeAll("anyframe->");
+                    return print(child.toType(), writer, mod);
+                },
 
                 // values, not types
                 .undef => unreachable,
@@ -1098,9 +1078,7 @@ pub const Type = struct {
 
                 // Pointers to zero-bit types still have a runtime address; however, pointers
                 // to comptime-only types do not, with the exception of function pointers.
-                .anyframe_T,
-                .pointer,
-                => {
+                .pointer => {
                     if (ignore_comptime_only) {
                         return true;
                     } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) {
@@ -1141,6 +1119,7 @@ pub const Type = struct {
                     if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
                     return !comptimeOnly(ty, mod);
                 },
+                .anyframe_type => true,
                 .array_type => |array_type| {
                     if (array_type.sentinel != .none) {
                         return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
@@ -1195,7 +1174,6 @@ pub const Type = struct {
                     .c_longdouble,
                     .bool,
                     .anyerror,
-                    .@"anyframe",
                     .anyopaque,
                     .atomic_order,
                     .atomic_rmw_op,
@@ -1319,7 +1297,6 @@ pub const Type = struct {
                 .error_set_inferred,
                 .error_set_merged,
                 .error_union,
-                .anyframe_T,
                 => false,
 
                 .inferred_alloc_mut => unreachable,
@@ -1336,6 +1313,7 @@ pub const Type = struct {
                 .error_union_type,
                 .anon_struct_type,
                 .opaque_type,
+                .anyframe_type,
                 // These are function bodies, not function pointers.
                 .func_type,
                 => false,
@@ -1366,7 +1344,6 @@ pub const Type = struct {
                     => true,
 
                     .anyerror,
-                    .@"anyframe",
                     .anyopaque,
                     .atomic_order,
                     .atomic_rmw_op,
@@ -1594,9 +1571,7 @@ pub const Type = struct {
         switch (ty.ip_index) {
             .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },
             .none => switch (ty.tag()) {
-                .pointer,
-                .anyframe_T,
-                => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
+                .pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
 
                 // TODO revisit this when we have the concept of the error tag type
                 .error_set_inferred,
@@ -1617,7 +1592,7 @@ pub const Type = struct {
                     if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
                     return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) };
                 },
-                .ptr_type => {
+                .ptr_type, .anyframe_type => {
                     return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
                 },
                 .array_type => |array_type| {
@@ -1657,7 +1632,6 @@ pub const Type = struct {
                     .isize,
                     .export_options,
                     .extern_options,
-                    .@"anyframe",
                     => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
 
                     .c_char => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.char) },
@@ -1976,8 +1950,6 @@ pub const Type = struct {
                 .inferred_alloc_const => unreachable,
                 .inferred_alloc_mut => unreachable,
 
-                .anyframe_T => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
-
                 .pointer => switch (ty.castTag(.pointer).?.data.size) {
                     .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
                     else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
@@ -2039,6 +2011,8 @@ pub const Type = struct {
                     .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
                     else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
                 },
+                .anyframe_type => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
+
                 .array_type => |array_type| {
                     const len = array_type.len + @boolToInt(array_type.sentinel != .none);
                     switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) {
@@ -2102,7 +2076,6 @@ pub const Type = struct {
 
                     .usize,
                     .isize,
-                    .@"anyframe",
                     => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
 
                     .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
@@ -2298,8 +2271,6 @@ pub const Type = struct {
                 .inferred_alloc_const => unreachable,
                 .inferred_alloc_mut => unreachable,
 
-                .anyframe_T => return target.ptrBitWidth(),
-
                 .pointer => switch (ty.castTag(.pointer).?.data.size) {
                     .Slice => return target.ptrBitWidth() * 2,
                     else => return target.ptrBitWidth(),
@@ -2323,6 +2294,8 @@ pub const Type = struct {
                     .Slice => return target.ptrBitWidth() * 2,
                     else => return target.ptrBitWidth() * 2,
                 },
+                .anyframe_type => return target.ptrBitWidth(),
+
                 .array_type => |array_type| {
                     const len = array_type.len + @boolToInt(array_type.sentinel != .none);
                     if (len == 0) return 0;
@@ -2349,7 +2322,6 @@ pub const Type = struct {
 
                     .usize,
                     .isize,
-                    .@"anyframe",
                     => return target.ptrBitWidth(),
 
                     .c_char => return target.c_type_bit_size(.char),
@@ -2777,8 +2749,6 @@ pub const Type = struct {
                 },
                 .optional => ty.castTag(.optional).?.data.childType(mod),
 
-                .anyframe_T => ty.castTag(.anyframe_T).?.data,
-
                 else => unreachable,
             },
             else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
@@ -2786,6 +2756,10 @@ pub const Type = struct {
                     .One => ptr_type.elem_type.toType().shallowElemType(mod),
                     .Many, .C, .Slice => ptr_type.elem_type.toType(),
                 },
+                .anyframe_type => |child| {
+                    assert(child != .none);
+                    return child.toType();
+                },
                 .vector_type => |vector_type| vector_type.child.toType(),
                 .array_type => |array_type| array_type.child.toType(),
                 .opt_type => |child| mod.intern_pool.childType(child).toType(),
@@ -3154,6 +3128,7 @@ pub const Type = struct {
                 .anon_struct_type => unreachable,
 
                 .ptr_type => unreachable,
+                .anyframe_type => unreachable,
                 .array_type => unreachable,
 
                 .opt_type => unreachable,
@@ -3327,7 +3302,6 @@ pub const Type = struct {
                 .error_set,
                 .error_set_merged,
                 .error_set_inferred,
-                .anyframe_T,
                 .pointer,
                 => return null,
 
@@ -3355,6 +3329,7 @@ pub const Type = struct {
                 .ptr_type,
                 .error_union_type,
                 .func_type,
+                .anyframe_type,
                 => return null,
 
                 .array_type => |array_type| {
@@ -3401,7 +3376,6 @@ pub const Type = struct {
                     .anyerror,
                     .comptime_int,
                     .comptime_float,
-                    .@"anyframe",
                     .enum_literal,
                     .atomic_order,
                     .atomic_rmw_op,
@@ -3555,10 +3529,6 @@ pub const Type = struct {
                 },
 
                 .error_union => return ty.errorUnionPayload().comptimeOnly(mod),
-                .anyframe_T => {
-                    const child_ty = ty.castTag(.anyframe_T).?.data;
-                    return child_ty.comptimeOnly(mod);
-                },
             },
             else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
                 .int_type => false,
@@ -3570,6 +3540,10 @@ pub const Type = struct {
                         return child_ty.comptimeOnly(mod);
                     }
                 },
+                .anyframe_type => |child| {
+                    if (child == .none) return false;
+                    return child.toType().comptimeOnly(mod);
+                },
                 .array_type => |array_type| array_type.child.toType().comptimeOnly(mod),
                 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),
                 .opt_type => |child| child.toType().comptimeOnly(mod),
@@ -3599,7 +3573,6 @@ pub const Type = struct {
                     .bool,
                     .void,
                     .anyerror,
-                    .@"anyframe",
                     .noreturn,
                     .generic_poison,
                     .atomic_order,
@@ -4245,7 +4218,6 @@ pub const Type = struct {
         pointer,
         optional,
         error_union,
-        anyframe_T,
         error_set,
         error_set_single,
         /// The type is the inferred error set of a specific function.
@@ -4261,9 +4233,7 @@ pub const Type = struct {
                 .inferred_alloc_mut,
                 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
 
-                .optional,
-                .anyframe_T,
-                => Payload.ElemType,
+                .optional => Payload.ElemType,
 
                 .error_set => Payload.ErrorSet,
                 .error_set_inferred => Payload.ErrorSetInferred,