diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index 3a9c7e6c59..b521e1543a 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -600,7 +600,11 @@ const CondKind = union(enum) { fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope { if (self == .bool) return &then_scope.base; - const payload = payload_node.?.castTag(.PointerPayload).?; + const payload = payload_node.?.castTag(.PointerPayload) orelse { + // condition is error union and payload is not explicitly ignored + _ = try addZIRUnOp(mod, &then_scope.base, src, .ensure_err_payload_void, self.err_union.?); + return &then_scope.base; + }; const is_ptr = payload.ptr_token != null; const ident_node = payload.value_symbol.castTag(.Identifier).?; diff --git a/src-self-hosted/zir.zig b/src-self-hosted/zir.zig index 276db6d522..ebc491c943 100644 --- a/src-self-hosted/zir.zig +++ b/src-self-hosted/zir.zig @@ -225,6 +225,8 @@ pub const Inst = struct { unwrap_err_safe, /// Same as previous, but without safety checks. Used for orelse, if and while unwrap_err_unsafe, + /// Takes a *E!T and raises a compiler error if T != void + ensure_err_payload_void, pub fn Type(tag: Tag) type { return switch (tag) { @@ -259,6 +261,7 @@ pub const Inst = struct { .unwrap_optional_unsafe, .unwrap_err_safe, .unwrap_err_unsafe, + .ensure_err_payload_void, => UnOp, .add, @@ -398,6 +401,7 @@ pub const Inst = struct { .unwrap_err_safe, .unwrap_err_unsafe, .ptr_type, + .ensure_err_payload_void, => false, .@"break", diff --git a/src-self-hosted/zir_sema.zig b/src-self-hosted/zir_sema.zig index 94c3a19677..d51d0d0f7f 100644 --- a/src-self-hosted/zir_sema.zig +++ b/src-self-hosted/zir_sema.zig @@ -112,6 +112,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! .unwrap_optional_unsafe => return analyzeInstUnwrapOptional(mod, scope, old_inst.castTag(.unwrap_optional_unsafe).?, false), .unwrap_err_safe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_safe).?, true), .unwrap_err_unsafe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_unsafe).?, false), + .ensure_err_payload_void => return analyzeInstEnsureErrPayloadVoid(mod, scope, old_inst.castTag(.ensure_err_payload_void).?), } } @@ -735,6 +736,10 @@ fn analyzeInstUnwrapErr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, saf return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstUnwrapErr", .{}); } +fn analyzeInstEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst { + return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstEnsureErrPayloadVoid", .{}); +} + fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst { const return_type = try resolveType(mod, scope, fntype.positionals.return_type);