Commit 0977e41407

Vexu <git@vexu.eu>
2020-08-18 09:36:57
stage2: ensure discarded error union payload is void
1 parent 60ea873
Changed files (3)
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).?;
 
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",
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);