Commit ff737cc648

Andrew Kelley <andrew@ziglang.org>
2019-06-26 18:31:51
fix peer type resolution: unreachable, error set, unreachable
1 parent b4e40cb
Changed files (3)
src
std
event
test
stage1
behavior
src/ir.cpp
@@ -10093,9 +10093,21 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
 {
     Error err;
     assert(instruction_count >= 1);
-    IrInstruction *prev_inst = instructions[0];
-    if (type_is_invalid(prev_inst->value.type)) {
-        return ira->codegen->builtin_types.entry_invalid;
+    IrInstruction *prev_inst;
+    size_t i = 0;
+    for (;;) {
+        prev_inst = instructions[i];
+        if (type_is_invalid(prev_inst->value.type)) {
+            return ira->codegen->builtin_types.entry_invalid;
+        }
+        if (prev_inst->value.type->id == ZigTypeIdUnreachable) {
+            i += 1;
+            if (i == instruction_count) {
+                return prev_inst->value.type;
+            }
+            continue;
+        }
+        break;
     }
     ErrorTableEntry **errors = nullptr;
     size_t errors_count = 0;
@@ -10120,7 +10132,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
 
     bool any_are_null = (prev_inst->value.type->id == ZigTypeIdNull);
     bool convert_to_const_slice = false;
-    for (size_t i = 1; i < instruction_count; i += 1) {
+    for (; i < instruction_count; i += 1) {
         IrInstruction *cur_inst = instructions[i];
         ZigType *cur_type = cur_inst->value.type;
         ZigType *prev_type = prev_inst->value.type;
@@ -10139,7 +10151,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
         }
 
         if (prev_type->id == ZigTypeIdErrorSet) {
-            assert(err_set_type != nullptr);
+            ir_assert(err_set_type != nullptr, prev_inst);
             if (cur_type->id == ZigTypeIdErrorSet) {
                 if (type_is_global_error_set(err_set_type)) {
                     continue;
std/event/fs.zig
@@ -1290,10 +1290,9 @@ pub fn Watch(comptime V: type) type {
                                 error.FileDescriptorAlreadyPresentInSet => unreachable,
                                 error.OperationCausesCircularLoop => unreachable,
                                 error.FileDescriptorNotRegistered => unreachable,
-                                error.SystemResources => error.SystemResources,
-                                error.UserResourceLimitReached => error.UserResourceLimitReached,
                                 error.FileDescriptorIncompatibleWithEpoll => unreachable,
                                 error.Unexpected => unreachable,
+                                else => |e| e,
                             };
                             await (async channel.put(transformed_err) catch unreachable);
                         };
test/stage1/behavior/cast.zig
@@ -496,3 +496,26 @@ test "peer type resolution: unreachable, null, slice" {
     };
     S.doTheTest(1, "hi");
 }
+
+test "peer type resolution: unreachable, error set, unreachable" {
+    const Error = error {
+        FileDescriptorAlreadyPresentInSet,
+        OperationCausesCircularLoop,
+        FileDescriptorNotRegistered,
+        SystemResources,
+        UserResourceLimitReached,
+        FileDescriptorIncompatibleWithEpoll,
+        Unexpected,
+    };
+    var err = Error.SystemResources;
+    const transformed_err = switch (err) {
+        error.FileDescriptorAlreadyPresentInSet => unreachable,
+        error.OperationCausesCircularLoop => unreachable,
+        error.FileDescriptorNotRegistered => unreachable,
+        error.SystemResources => error.SystemResources,
+        error.UserResourceLimitReached => error.UserResourceLimitReached,
+        error.FileDescriptorIncompatibleWithEpoll => unreachable,
+        error.Unexpected => unreachable,
+    };
+    expect(transformed_err == error.SystemResources);
+}