From 53bc4c80d4d9769b79afdd4c3a104de5e6bf103d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Fri, 20 May 2022 18:34:53 +0200 Subject: [PATCH] checker,cgen: allow result if guard (#14474) --- vlib/v/checker/checker.v | 14 +++++++------- vlib/v/checker/containers.v | 2 +- .../tests/expression_should_return_an_option.out | 4 ++-- vlib/v/gen/c/if.v | 12 ++++++++++-- vlib/v/tests/results_test.v | 13 +++++++++++++ 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b074530dcd..52eb09b515 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2150,25 +2150,25 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type { c.inside_if_guard = true node.expr_type = c.expr(node.expr) c.inside_if_guard = old_inside_if_guard - if !node.expr_type.has_flag(.optional) { - mut no_opt := true + if !node.expr_type.has_flag(.optional) && !node.expr_type.has_flag(.result) { + mut no_opt_or_res := true match mut node.expr { ast.IndexExpr { - no_opt = false + no_opt_or_res = false node.expr_type = node.expr_type.set_flag(.optional) node.expr.is_option = true } ast.PrefixExpr { if node.expr.op == .arrow { - no_opt = false + no_opt_or_res = false node.expr_type = node.expr_type.set_flag(.optional) node.expr.is_option = true } } else {} } - if no_opt { - c.error('expression should return an option', node.expr.pos()) + if no_opt_or_res { + c.error('expression should either return an option or a result', node.expr.pos()) } } return ast.bool_type @@ -2676,7 +2676,7 @@ pub fn (mut c Checker) ident(mut node ast.Ident) ast.Type { } } } else { - typ = obj.expr.expr_type.clear_flag(.optional) + typ = obj.expr.expr_type.clear_flag(.optional).clear_flag(.result) } } else { typ = c.expr(obj.expr) diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index 6de8281865..8a66b9c43c 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -80,7 +80,7 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { // } array_info := type_sym.array_info() node.elem_type = array_info.elem_type - // clear optional flag incase of: `fn opt_arr ?[]int { return [] }` + // clear optional flag incase of: `fn opt_arr() ?[]int { return [] }` return if c.expected_type.has_flag(.shared_f) { c.expected_type.clear_flag(.shared_f).deref() } else { diff --git a/vlib/v/checker/tests/expression_should_return_an_option.out b/vlib/v/checker/tests/expression_should_return_an_option.out index e150341676..3337fc1131 100644 --- a/vlib/v/checker/tests/expression_should_return_an_option.out +++ b/vlib/v/checker/tests/expression_should_return_an_option.out @@ -1,7 +1,7 @@ -vlib/v/checker/tests/expression_should_return_an_option.vv:28:10: error: expression should return an option +vlib/v/checker/tests/expression_should_return_an_option.vv:28:10: error: expression should either return an option or a result 26 | } 27 | // should be an checker error: 28 | if x := return_string() { | ~~~~~~~~~~~~~~~ 29 | println('x: $x') - 30 | } + 30 | } \ No newline at end of file diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index 61503c8b85..4c483ae96a 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -132,11 +132,19 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { var_name = g.new_tmp_var() guard_vars[i] = var_name // for `else` g.tmp_count-- - g.writeln('if (${var_name}.state == 0) {') + if branch.cond.expr_type.has_flag(.optional) { + g.writeln('if (${var_name}.state == 0) {') + } else if branch.cond.expr_type.has_flag(.result) { + g.writeln('if (!${var_name}.is_error) {') + } } else { g.write('if ($var_name = ') g.expr(branch.cond.expr) - g.writeln(', ${var_name}.state == 0) {') + if branch.cond.expr_type.has_flag(.optional) { + g.writeln(', ${var_name}.state == 0) {') + } else if branch.cond.expr_type.has_flag(.result) { + g.writeln(', !${var_name}.is_error) {') + } } if short_opt || branch.cond.vars[0].name != '_' { base_type := g.base_type(branch.cond.expr_type) diff --git a/vlib/v/tests/results_test.v b/vlib/v/tests/results_test.v index 9675517581..3cca61ea5e 100644 --- a/vlib/v/tests/results_test.v +++ b/vlib/v/tests/results_test.v @@ -81,3 +81,16 @@ fn return_reference_type(path string) !&string { str := '' return &str } + +fn read() !string { + return '' +} + +fn test_results_if_guard() { + if fcontent := read() { + assert fcontent == '' + assert '$fcontent' == '' + return + } + assert false +}