Commit 96931228af

Andrew Kelley <andrew@ziglang.org>
2019-06-19 22:29:46
fix comptime test error for empty error set
1 parent 974db23
Changed files (4)
src/all_types.hpp
@@ -3085,6 +3085,7 @@ struct IrInstructionAlignOf {
 struct IrInstructionTestErrSrc {
     IrInstruction base;
 
+    bool resolve_err_set;
     IrInstruction *base_ptr;
 };
 
src/codegen.cpp
@@ -4913,6 +4913,9 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
 static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
         IrInstructionUnwrapErrCode *instruction)
 {
+    if (instruction->base.value.special != ConstValSpecialRuntime)
+        return nullptr;
+
     ZigType *ptr_type = instruction->err_union_ptr->value.type;
     assert(ptr_type->id == ZigTypeIdPointer);
     ZigType *err_union_type = ptr_type->data.pointer.child_type;
@@ -4930,6 +4933,9 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
 static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
         IrInstructionUnwrapErrPayload *instruction)
 {
+    if (instruction->base.value.special != ConstValSpecialRuntime)
+        return nullptr;
+
     bool want_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base) &&
         g->errors_by_index.length > 1;
     if (!want_safety && !type_has_bits(instruction->base.value.type))
src/ir.cpp
@@ -2446,10 +2446,11 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s
 }
 
 static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
-    IrInstruction *base_ptr)
+    IrInstruction *base_ptr, bool resolve_err_set)
 {
     IrInstructionTestErrSrc *instruction = ir_build_instruction<IrInstructionTestErrSrc>(irb, scope, source_node);
     instruction->base_ptr = base_ptr;
+    instruction->resolve_err_set = resolve_err_set;
 
     ir_ref_instruction(base_ptr, irb->current_basic_block);
 
@@ -3593,7 +3594,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
 
                     IrInstruction *ret_ptr = ir_build_result_ptr(irb, scope, node, &result_loc_ret->base,
                             return_value);
-                    IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr);
+                    IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, ret_ptr, false);
 
                     bool should_inline = ir_should_inline(irb->exec, scope);
                     IrInstruction *is_comptime;
@@ -3639,7 +3640,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
                 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
                 if (err_union_ptr == irb->codegen->invalid_instruction)
                     return irb->codegen->invalid_instruction;
-                IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr);
+                IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true);
 
                 IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
                 IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
@@ -5987,7 +5988,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
                 LValPtr, nullptr);
         if (err_val_ptr == irb->codegen->invalid_instruction)
             return err_val_ptr;
-        IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr);
+        IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, true);
         IrBasicBlock *after_cond_block = irb->current_basic_block;
         IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
         IrInstruction *cond_br_inst;
@@ -6771,7 +6772,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
         return err_val_ptr;
 
     IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
-    IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr);
+    IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true);
 
     IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk");
     IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse");
@@ -7381,7 +7382,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
     if (err_union_ptr == irb->codegen->invalid_instruction)
         return irb->codegen->invalid_instruction;
 
-    IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr);
+    IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true);
 
     IrInstruction *is_comptime;
     if (ir_should_inline(irb->exec, parent_scope)) {
@@ -22512,6 +22513,19 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
             }
         }
 
+        if (instruction->resolve_err_set) {
+            ZigType *err_set_type = type_entry->data.error_union.err_set_type;
+            if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) {
+                return ira->codegen->invalid_instruction;
+            }
+            if (!type_is_global_error_set(err_set_type) &&
+                err_set_type->data.error_set.err_count == 0)
+            {
+                assert(err_set_type->data.error_set.infer_fn == nullptr);
+                return ir_const_bool(ira, &instruction->base, false);
+            }
+        }
+
         return ir_build_test_err_gen(ira, &instruction->base, value);
     } else if (type_entry->id == ZigTypeIdErrorSet) {
         return ir_const_bool(ira, &instruction->base, true);
test/stage1/behavior/error.zig
@@ -130,10 +130,10 @@ fn testExplicitErrorSetCast(set1: Set1) void {
     expect(y == error.A);
 }
 
-//test "comptime test error for empty error set" {
-//    testComptimeTestErrorEmptySet(1234);
-//    comptime testComptimeTestErrorEmptySet(1234);
-//}
+test "comptime test error for empty error set" {
+    testComptimeTestErrorEmptySet(1234);
+    comptime testComptimeTestErrorEmptySet(1234);
+}
 
 const EmptyErrorSet = error{};
 
@@ -204,10 +204,10 @@ fn foo2(f: fn () anyerror!void) void {
 
 fn bar2() (error{}!void) {}
 
-//test "error: Zero sized error set returned with value payload crash" {
-//    _ = foo3(0) catch {};
-//    _ = comptime foo3(0) catch {};
-//}
+test "error: Zero sized error set returned with value payload crash" {
+    _ = foo3(0) catch {};
+    _ = comptime foo3(0) catch {};
+}
 
 const Error = error{};
 fn foo3(b: usize) Error!usize {