Commit 16d7db59ed

Vexu <git@vexu.eu>
2020-08-22 15:30:57
stage2: anyframe and error union types
1 parent d62c12e
src-self-hosted/astgen.zig
@@ -267,11 +267,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
         .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)),
         .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)),
         .SliceType => return rlWrap(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)),
+        .ErrorUnion => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)),
+        .MergeErrorSets => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)),
+        .AnyFrameType => return rlWrap(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),
 
         .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
         .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
-        .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}),
-        .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}),
         .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}),
         .OrElse => return mod.failNode(scope, node, "TODO implement astgen.expr for .OrElse", .{}),
         .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}),
@@ -290,7 +291,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
         .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),
         .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}),
         .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),
-        .AnyFrameType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyFrameType", .{}),
         .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}),
         .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
         .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),
@@ -566,14 +566,13 @@ fn negation(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp, op_inst
     const tree = scope.tree();
     const src = tree.token_locs[node.op_token].start;
 
-    const lhs = addZIRInstConst(mod, scope, src, .{
+    const lhs = try addZIRInstConst(mod, scope, src, .{
         .ty = Type.initTag(.comptime_int),
         .val = Value.initTag(.zero),
     });
     const rhs = try expr(mod, scope, .none, node.rhs);
 
-    const result = try addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);
-    return rlWrap(mod, scope, rl, result);
+    return addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);
 }
 
 fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
@@ -703,6 +702,36 @@ fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSenti
     }, .{});
 }
 
+fn anyFrameType(mod: *Module, scope: *Scope, node: *ast.Node.AnyFrameType) InnerError!*zir.Inst {
+    const tree = scope.tree();
+    const src = tree.token_locs[node.anyframe_token].start;
+    if (node.result) |some| {
+        const meta_type = try addZIRInstConst(mod, scope, src, .{
+            .ty = Type.initTag(.type),
+            .val = Value.initTag(.type_type),
+        });
+        const return_type = try expr(mod, scope, .{ .ty = meta_type}, some.return_type);
+        return addZIRUnOp(mod, scope, src, .anyframe_type, return_type);
+    } else {
+        return addZIRInstConst(mod, scope, src, .{
+            .ty = Type.initTag(.type),
+            .val = Value.initTag(.anyframe_type),
+        });
+    }
+}
+
+fn typeInixOp(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp, op_inst_tag: zir.Inst.Tag) InnerError!*zir.Inst {
+    const tree = scope.tree();
+    const src = tree.token_locs[node.op_token].start;
+    const meta_type = try addZIRInstConst(mod, scope, src, .{
+        .ty = Type.initTag(.type),
+        .val = Value.initTag(.type_type),
+    });
+    const error_set = try expr(mod, scope, .{ .ty = meta_type }, node.lhs);
+    const payload = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
+    return addZIRBinOp(mod, scope, src, op_inst_tag, error_set, payload);
+}
+
 fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.EnumLiteral) !*zir.Inst {
     const tree = scope.tree();
     const src = tree.token_locs[node.name].start;
src-self-hosted/Module.zig
@@ -3309,6 +3309,28 @@ pub fn arrayType(self: *Module, scope: *Scope, len: u64, sentinel: ?Value, elem_
     return Type.initPayload(&payload.base);
 }
 
+pub fn errorUnionType(self: *Module, scope: *Scope, error_set: Type, payload: Type) Allocator.Error!Type {
+    assert(error_set.zigTypeTag() == .ErrorSet);
+    if (error_set.eql(Type.initTag(.anyerror)) and payload.eql(Type.initTag(.void))) {
+        return Type.initTag(.anyerror_void_error_union);
+    }
+
+    const result = try scope.arena().create(Type.Payload.ErrorUnion);
+    result.* = .{
+        .error_set = error_set,
+        .payload = payload,
+    };
+    return Type.initPayload(&result.base);
+}
+
+pub fn anyframeType(self: *Module, scope: *Scope, return_type: Type) Allocator.Error!Type {
+    const result = try scope.arena().create(Type.Payload.AnyFrame);
+    result.* = .{
+        .return_type = return_type,
+    };
+    return Type.initPayload(&result.base);
+}
+
 pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void {
     const zir_module = scope.namespace();
     const source = zir_module.getSource(self) catch @panic("dumpInst failed to get source");
src-self-hosted/type.zig
@@ -84,6 +84,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             => return .Optional,
             .enum_literal => return .EnumLiteral,
+
+            .anyerror_void_error_union, .error_union => return .ErrorUnion,
+
+            .anyframe_T, .@"anyframe" => return .AnyFrame,
         }
     }
 
@@ -151,6 +155,9 @@ pub const Type = extern union {
             .ComptimeInt => return true,
             .Undefined => return true,
             .Null => return true,
+            .AnyFrame => {
+                return a.elemType().eql(b.elemType());
+            },
             .Pointer => {
                 // Hot path for common case:
                 if (a.castPointer()) |a_payload| {
@@ -225,7 +232,6 @@ pub const Type = extern union {
             .BoundFn,
             .Opaque,
             .Frame,
-            .AnyFrame,
             .Vector,
             => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
         }
@@ -343,6 +349,8 @@ pub const Type = extern union {
             .single_const_pointer_to_comptime_int,
             .const_slice_u8,
             .enum_literal,
+            .anyerror_void_error_union,
+            .@"anyframe",
             => unreachable,
 
             .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0),
@@ -397,6 +405,7 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"),
+            .anyframe_T => return self.copyPayloadSingleField(allocator, Payload.AnyFrame, "return_type"),
 
             .pointer => {
                 const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
@@ -416,6 +425,17 @@ pub const Type = extern union {
                 };
                 return Type{ .ptr_otherwise = &new_payload.base };
             },
+            .error_union => {
+                const payload = @fieldParentPtr(Payload.ErrorUnion, "base", self.ptr_otherwise);
+                const new_payload = try allocator.create(Payload.ErrorUnion);
+                new_payload.* = .{
+                    .base = payload.base,
+
+                    .error_set = try payload.error_set.copy(allocator),
+                    .payload = try payload.payload.copy(allocator),
+                };
+                return Type{ .ptr_otherwise = &new_payload.base };
+            },
         }
     }
 
@@ -482,6 +502,8 @@ pub const Type = extern union {
                 .@"null" => return out_stream.writeAll("@TypeOf(null)"),
                 .@"undefined" => return out_stream.writeAll("@TypeOf(undefined)"),
 
+                .@"anyframe" => return out_stream.writeAll("anyframe"),
+                .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),
                 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
                 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),
                 .fn_void_no_args => return out_stream.writeAll("fn() void"),
@@ -500,6 +522,12 @@ pub const Type = extern union {
                     continue;
                 },
 
+                .anyframe_T => {
+                    const payload = @fieldParentPtr(Payload.AnyFrame, "base", ty.ptr_otherwise);
+                    try out_stream.print("anyframe->", .{});
+                    ty = payload.return_type;
+                    continue;
+                },
                 .array_u8 => {
                     const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise);
                     return out_stream.print("[{}]u8", .{payload.len});
@@ -622,6 +650,13 @@ pub const Type = extern union {
                     ty = payload.pointee_type;
                     continue;
                 },
+                .error_union => {
+                    const payload = @fieldParentPtr(Payload.ErrorUnion, "base", ty.ptr_otherwise);
+                    try payload.error_set.format("", .{}, out_stream);
+                    try out_stream.writeAll("!");
+                    ty = payload.payload;
+                    continue;
+                },
             }
             unreachable;
         }
@@ -715,6 +750,9 @@ pub const Type = extern union {
             .optional,
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => true,
             // TODO lazy types
             .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
@@ -723,6 +761,11 @@ pub const Type = extern union {
             .int_signed => self.cast(Payload.IntSigned).?.bits == 0,
             .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,
 
+            .error_union => {
+                const payload = self.cast(Payload.ErrorUnion).?;
+                return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits();
+            },
+
             .c_void,
             .void,
             .type,
@@ -779,6 +822,8 @@ pub const Type = extern union {
             .mut_slice,
             .optional_single_const_pointer,
             .optional_single_mut_pointer,
+            .@"anyframe",
+            .anyframe_T,
             => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
 
             .pointer => {
@@ -803,7 +848,7 @@ pub const Type = extern union {
             .f128 => return 16,
             .c_longdouble => return 16,
 
-            .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
+            .anyerror_void_error_union, .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
 
             .array, .array_sentinel => return self.elemType().abiAlignment(target),
 
@@ -829,6 +874,16 @@ pub const Type = extern union {
                 return child_type.abiAlignment(target);
             },
 
+            .error_union => {
+                const payload = self.cast(Payload.ErrorUnion).?;
+                if (!payload.error_set.hasCodeGenBits()) {
+                    return payload.payload.abiAlignment(target);
+                } else if (!payload.payload.hasCodeGenBits()) {
+                    return payload.error_set.abiAlignment(target);
+                }
+                @panic("TODO abiAlignment error union");
+            },
+
             .c_void,
             .void,
             .type,
@@ -882,12 +937,15 @@ pub const Type = extern union {
             .i32, .u32 => return 4,
             .i64, .u64 => return 8,
 
-            .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
+            .@"anyframe", .anyframe_T, .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8),
 
             .const_slice,
             .mut_slice,
-            .const_slice_u8,
-            => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
+            => {
+                if (self.elemType().hasCodeGenBits()) return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2;
+                return @divExact(target.cpu.arch.ptrBitWidth(), 8);
+            },
+            .const_slice_u8 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
 
             .optional_single_const_pointer,
             .optional_single_mut_pointer,
@@ -923,7 +981,7 @@ pub const Type = extern union {
             .f128 => return 16,
             .c_longdouble => return 16,
 
-            .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
+            .anyerror_void_error_union, .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type
 
             .int_signed, .int_unsigned => {
                 const bits: u16 = if (self.cast(Payload.IntSigned)) |pl|
@@ -950,6 +1008,18 @@ pub const Type = extern union {
                 // to the child type's ABI alignment.
                 return child_type.abiAlignment(target) + child_type.abiSize(target);
             },
+
+            .error_union => {
+                const payload = self.cast(Payload.ErrorUnion).?;
+                if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) {
+                    return 0;
+                } else if (!payload.error_set.hasCodeGenBits()) {
+                    return payload.payload.abiSize(target);
+                } else if (!payload.payload.hasCodeGenBits()) {
+                    return payload.error_set.abiSize(target);
+                }
+                @panic("TODO abiSize error union");
+            },
         };
     }
 
@@ -1010,6 +1080,10 @@ pub const Type = extern union {
             .c_mut_pointer,
             .const_slice,
             .mut_slice,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
 
             .single_const_pointer,
@@ -1078,6 +1152,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
 
             .const_slice,
@@ -1143,6 +1221,10 @@ pub const Type = extern union {
             .optional_single_const_pointer,
             .enum_literal,
             .mut_slice,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
 
             .single_const_pointer,
@@ -1217,6 +1299,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
 
             .pointer => {
@@ -1328,6 +1414,10 @@ pub const Type = extern union {
             .optional_single_const_pointer,
             .optional_single_mut_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
 
             .array => self.cast(Payload.Array).?.elem_type,
@@ -1449,6 +1539,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
 
             .array => self.cast(Payload.Array).?.len,
@@ -1516,6 +1610,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
 
             .array, .array_u8 => return null,
@@ -1581,6 +1679,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
 
             .int_signed,
@@ -1649,6 +1751,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
 
             .int_unsigned,
@@ -1707,6 +1813,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
 
             .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
@@ -1783,6 +1893,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
 
             .usize,
@@ -1888,6 +2002,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
         };
     }
@@ -1959,6 +2077,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
         }
     }
@@ -2029,6 +2151,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
         }
     }
@@ -2099,6 +2225,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
         };
     }
@@ -2166,6 +2296,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
         };
     }
@@ -2233,6 +2367,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => unreachable,
         };
     }
@@ -2300,6 +2438,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => false,
         };
     }
@@ -2351,6 +2493,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .anyerror_void_error_union,
+            .anyframe_T,
+            .@"anyframe",
+            .error_union,
             => return null,
 
             .void => return Value.initTag(.void_value),
@@ -2454,6 +2600,10 @@ pub const Type = extern union {
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
             .enum_literal,
+            .error_union,
+            .@"anyframe",
+            .anyframe_T,
+            .anyerror_void_error_union,
             => return false,
 
             .c_const_pointer,
@@ -2511,6 +2661,8 @@ pub const Type = extern union {
         fn_naked_noreturn_no_args,
         fn_ccc_void_no_args,
         single_const_pointer_to_comptime_int,
+        anyerror_void_error_union,
+        @"anyframe",
         const_slice_u8, // See last_no_payload_tag below.
         // After this, the tag requires a payload.
 
@@ -2533,6 +2685,8 @@ pub const Type = extern union {
         optional,
         optional_single_mut_pointer,
         optional_single_const_pointer,
+        error_union,
+        anyframe_T,
 
         pub const last_no_payload_tag = Tag.const_slice_u8;
         pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -2614,6 +2768,19 @@ pub const Type = extern union {
             @"volatile": bool,
             size: std.builtin.TypeInfo.Pointer.Size,
         };
+
+        pub const ErrorUnion = struct {
+            base: Payload = .{ .tag = .error_union },
+
+            error_set: Type,
+            payload: Type,
+        };
+
+        pub const AnyFrame = struct {
+            base: Payload = .{ .tag = .anyframe_T },
+
+            return_type: Type,
+        };
     };
 };
 
src-self-hosted/value.zig
@@ -61,6 +61,7 @@ pub const Value = extern union {
         single_const_pointer_to_comptime_int_type,
         const_slice_u8_type,
         enum_literal_type,
+        anyframe_type,
 
         undef,
         zero,
@@ -168,6 +169,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .undef,
             .zero,
             .void_value,
@@ -300,6 +302,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
             .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
             .enum_literal_type => return out_stream.writeAll("@TypeOf(.EnumLiteral)"),
+            .anyframe_type => return out_stream.writeAll("anyframe"),
 
             .null_value => return out_stream.writeAll("null"),
             .undef => return out_stream.writeAll("undefined"),
@@ -408,6 +411,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
             .const_slice_u8_type => Type.initTag(.const_slice_u8),
             .enum_literal_type => Type.initTag(.enum_literal),
+            .anyframe_type => Type.initTag(.@"anyframe"),
 
             .undef,
             .zero,
@@ -482,6 +486,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .null_value,
             .function,
             .variable,
@@ -560,6 +565,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .null_value,
             .function,
             .variable,
@@ -638,6 +644,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .null_value,
             .function,
             .variable,
@@ -742,6 +749,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .null_value,
             .function,
             .variable,
@@ -825,6 +833,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .null_value,
             .function,
             .variable,
@@ -988,6 +997,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .bool_true,
             .bool_false,
             .null_value,
@@ -1063,6 +1073,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .null_value,
             .function,
             .variable,
@@ -1197,6 +1208,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .zero,
             .bool_true,
             .bool_false,
@@ -1276,6 +1288,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .zero,
             .bool_true,
             .bool_false,
@@ -1372,6 +1385,7 @@ pub const Value = extern union {
             .single_const_pointer_to_comptime_int_type,
             .const_slice_u8_type,
             .enum_literal_type,
+            .anyframe_type,
             .zero,
             .empty_array,
             .bool_true,
src-self-hosted/zir.zig
@@ -43,6 +43,8 @@ pub const Inst = struct {
         alloc,
         /// Same as `alloc` except the type is inferred.
         alloc_inferred,
+        /// Create an `anyframe->T`.
+        anyframe_type,
         /// Array concatenation. `a ++ b`
         array_cat,
         /// Array multiplication `a ** b`
@@ -135,6 +137,8 @@ pub const Inst = struct {
         ensure_result_used,
         /// Emits a compile error if an error is ignored.
         ensure_result_non_error,
+        /// Create a `E!T` type.
+        error_union_type,
         /// Export the provided Decl as the provided name in the compilation's output object file.
         @"export",
         /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
@@ -162,6 +166,8 @@ pub const Inst = struct {
         /// A labeled block of code that loops forever. At the end of the body it is implied
         /// to repeat; no explicit "repeat" instruction terminates loop bodies.
         loop,
+        /// Merge two error sets into one, `E1 || E2`.
+        merge_error_sets,
         /// Ambiguously remainder division or modulus. If the computation would possibly have
         /// a different value depending on whether the operation is remainder division or modulus,
         /// a compile error is emitted. Otherwise the computation is performed.
@@ -288,6 +294,8 @@ pub const Inst = struct {
                 .unwrap_err_safe,
                 .unwrap_err_unsafe,
                 .ensure_err_payload_void,
+                .anyframe_type,
+                .bitnot,
                 => UnOp,
 
                 .add,
@@ -318,6 +326,8 @@ pub const Inst = struct {
                 .bitcast,
                 .coerce_result_ptr,
                 .xor,
+                .error_union_type,
+                .merge_error_sets,
                 => BinOp,
 
                 .arg => Arg,
@@ -440,6 +450,10 @@ pub const Inst = struct {
                 .ptr_type,
                 .ensure_err_payload_void,
                 .enum_literal,
+                .merge_error_sets,
+                .anyframe_type,
+                .error_union_type,
+                .bitnot,
                 => false,
 
                 .@"break",
src-self-hosted/zir_sema.zig
@@ -97,7 +97,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
         .array_cat => return analyzeInstArrayCat(mod, scope, old_inst.castTag(.array_cat).?),
         .array_mul => return analyzeInstArrayMul(mod, scope, old_inst.castTag(.array_mul).?),
         .bitand => return analyzeInstBitwise(mod, scope, old_inst.castTag(.bitand).?),
-        .bitnot => return analyzeInstBitwise(mod, scope, old_inst.castTag(.bitnot).?),
+        .bitnot => return analyzeInstBitNot(mod, scope, old_inst.castTag(.bitnot).?),
         .bitor => return analyzeInstBitwise(mod, scope, old_inst.castTag(.bitor).?),
         .xor => return analyzeInstBitwise(mod, scope, old_inst.castTag(.xor).?),
         .shl => return analyzeInstShl(mod, scope, old_inst.castTag(.shl).?),
@@ -123,6 +123,9 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
         .array_type => return analyzeInstArrayType(mod, scope, old_inst.castTag(.array_type).?),
         .array_type_sentinel => return analyzeInstArrayTypeSentinel(mod, scope, old_inst.castTag(.array_type_sentinel).?),
         .enum_literal => return analyzeInstEnumLiteral(mod, scope, old_inst.castTag(.enum_literal).?),
+        .merge_error_sets => return analyzeInstMergeErrorSets(mod, scope, old_inst.castTag(.merge_error_sets).?),
+        .error_union_type => return analyzeInstErrorUnionType(mod, scope, old_inst.castTag(.error_union_type).?),
+        .anyframe_type => return analyzeInstAnyframeType(mod, scope, old_inst.castTag(.anyframe_type).?),
     }
 }
 
@@ -717,6 +720,27 @@ fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.Ar
     return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), sentinel.val, elem_type));
 }
 
+fn analyzeInstErrorUnionType(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
+    const error_union = try resolveType(mod, scope, inst.positionals.lhs);
+    const payload = try resolveType(mod, scope, inst.positionals.rhs);
+
+    if (error_union.zigTypeTag() != .ErrorSet) {
+        return mod.fail(scope, inst.base.src, "expected error set type, found {}", .{error_union.elemType()});
+    }
+
+    return mod.constType(scope, inst.base.src, try mod.errorUnionType(scope, error_union, payload));
+}
+
+fn analyzeInstAnyframeType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
+    const return_type = try resolveType(mod, scope, inst.positionals.operand);
+
+    return mod.constType(scope, inst.base.src, try mod.anyframeType(scope, return_type));
+}
+
+fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
+    return mod.fail(scope, inst.base.src, "TODO implement merge_error_sets", .{});
+}
+
 fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst {
     const payload = try scope.arena().create(Value.Payload.Bytes);
     payload.* = .{
@@ -984,6 +1008,10 @@ fn analyzeInstBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerE
     return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitwise", .{});
 }
 
+fn analyzeInstBitNot(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
+    return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitNot", .{});
+}
+
 fn analyzeInstArrayCat(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
     return mod.fail(scope, inst.base.src, "TODO implement analyzeInstArrayCat", .{});
 }