From 0efe441dfd422d4bfe501d5fbfbf15bd5951b494 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 8 Feb 2018 22:18:13 -0500 Subject: if statements support comptime known test error, runtime payload --- TODO | 23 +---------------------- src/ir.cpp | 11 ++++------- test/cases/error.zig | 11 +++++++++++ 3 files changed, 16 insertions(+), 29 deletions(-) diff --git a/TODO b/TODO index 2f3f25c3d3..f67feb1630 100644 --- a/TODO +++ b/TODO @@ -1,25 +1,3 @@ -sed -i 's/\(\bfn .*) \)%\(.*{\)$/\1!\2/g' $(find . -name "*.zig") - - -the literal translation of `%T` to this new code is `error!T`. -however this would not take advantage of error sets. It's -recommended to generally have all your functions which return possible -errors to use error set inference, like this: - -fn foo() !void { - -} - -then you can return void, or any error, and the error set is inferred. - - -you can get the compiler to tell you the possible errors for an inferred error set like this: - -foo() catch |err| switch (err) {}; - - -test err should be comptime if error set has 0 members - comptime calling fn with inferred error set should give empty error set but still you can use try comptime err to int of empty err set and of size 1 err set @@ -35,3 +13,4 @@ syntax - (error{}!void) as the return type passing a fn()error{}!T to a fn()error!T should be a compile error, they're not compatible + diff --git a/src/ir.cpp b/src/ir.cpp index fa2815d6dd..5f7e02848a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4800,12 +4800,8 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse"); IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "TryEnd"); - IrInstruction *is_comptime; - if (ir_should_inline(irb->exec, scope)) { - is_comptime = ir_build_const_bool(irb, scope, node, true); - } else { - is_comptime = ir_build_test_comptime(irb, scope, node, is_err); - } + bool force_comptime = ir_should_inline(irb->exec, scope); + IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, ok_block); @@ -4814,8 +4810,9 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * if (var_symbol) { IrInstruction *var_type = nullptr; bool is_shadowable = false; + IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, err_val); VariableTableEntry *var = ir_create_var(irb, node, scope, - var_symbol, var_is_const, var_is_const, is_shadowable, is_comptime); + var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, scope, node, err_val_ptr, false); IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); diff --git a/test/cases/error.zig b/test/cases/error.zig index 3d2835e723..a8150620b2 100644 --- a/test/cases/error.zig +++ b/test/cases/error.zig @@ -123,3 +123,14 @@ fn testExplicitErrorSetCast(set1: Set1) void { var y = Set1(x); assert(y == error.A); } + +test "comptime test error for empty error set" { + testComptimeTestErrorEmptySet(1234); + comptime testComptimeTestErrorEmptySet(1234); +} + +const EmptyErrorSet = error {}; + +fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { + if (x) |v| assert(v == 1234) else |err| @compileError("bad"); +} -- cgit v1.2.3