From 96931228af745b8e69c138b3b83893dafa166cfe Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 19 Jun 2019 16:29:46 -0400 Subject: [PATCH] fix comptime test error for empty error set --- src/all_types.hpp | 1 + src/codegen.cpp | 6 ++++++ src/ir.cpp | 26 ++++++++++++++++++++------ test/stage1/behavior/error.zig | 16 ++++++++-------- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index efb74e5ec..e376c4d4e 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -3085,6 +3085,7 @@ struct IrInstructionAlignOf { struct IrInstructionTestErrSrc { IrInstruction base; + bool resolve_err_set; IrInstruction *base_ptr; }; diff --git a/src/codegen.cpp b/src/codegen.cpp index bd3bae66f..05bdf9255 100644 --- a/src/codegen.cpp +++ b/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)) diff --git a/src/ir.cpp b/src/ir.cpp index 6dfaa168e..6de4202c5 100644 --- a/src/ir.cpp +++ b/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(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); diff --git a/test/stage1/behavior/error.zig b/test/stage1/behavior/error.zig index 1f8f8b36e..861c50075 100644 --- a/test/stage1/behavior/error.zig +++ b/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 {