diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index c0d1d0d654..f97254f29a 100644 --- a/src-self-hosted/Module.zig +++ b/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"); diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index 210ba0008e..32041fbc2b 100644 --- a/src-self-hosted/astgen.zig +++ b/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; diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index 37b13c1d15..37f9f0c638 100644 --- a/src-self-hosted/type.zig +++ b/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, + }; }; }; diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index 95a0746e19..7b43c66200 100644 --- a/src-self-hosted/value.zig +++ b/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, diff --git a/src-self-hosted/zir.zig b/src-self-hosted/zir.zig index a5d91aa690..9460e3b2bb 100644 --- a/src-self-hosted/zir.zig +++ b/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", diff --git a/src-self-hosted/zir_sema.zig b/src-self-hosted/zir_sema.zig index 6ac29e02c9..bfe58daf7e 100644 --- a/src-self-hosted/zir_sema.zig +++ b/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", .{}); }