checker,cgen: allow result if guard (#14474)
parent
ec5ccb2995
commit
53bc4c80d4
|
@ -2150,25 +2150,25 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
|
||||||
c.inside_if_guard = true
|
c.inside_if_guard = true
|
||||||
node.expr_type = c.expr(node.expr)
|
node.expr_type = c.expr(node.expr)
|
||||||
c.inside_if_guard = old_inside_if_guard
|
c.inside_if_guard = old_inside_if_guard
|
||||||
if !node.expr_type.has_flag(.optional) {
|
if !node.expr_type.has_flag(.optional) && !node.expr_type.has_flag(.result) {
|
||||||
mut no_opt := true
|
mut no_opt_or_res := true
|
||||||
match mut node.expr {
|
match mut node.expr {
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
no_opt = false
|
no_opt_or_res = false
|
||||||
node.expr_type = node.expr_type.set_flag(.optional)
|
node.expr_type = node.expr_type.set_flag(.optional)
|
||||||
node.expr.is_option = true
|
node.expr.is_option = true
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
if node.expr.op == .arrow {
|
if node.expr.op == .arrow {
|
||||||
no_opt = false
|
no_opt_or_res = false
|
||||||
node.expr_type = node.expr_type.set_flag(.optional)
|
node.expr_type = node.expr_type.set_flag(.optional)
|
||||||
node.expr.is_option = true
|
node.expr.is_option = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
if no_opt {
|
if no_opt_or_res {
|
||||||
c.error('expression should return an option', node.expr.pos())
|
c.error('expression should either return an option or a result', node.expr.pos())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ast.bool_type
|
return ast.bool_type
|
||||||
|
@ -2676,7 +2676,7 @@ pub fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
typ = obj.expr.expr_type.clear_flag(.optional)
|
typ = obj.expr.expr_type.clear_flag(.optional).clear_flag(.result)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
typ = c.expr(obj.expr)
|
typ = c.expr(obj.expr)
|
||||||
|
|
|
@ -80,7 +80,7 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||||
// }
|
// }
|
||||||
array_info := type_sym.array_info()
|
array_info := type_sym.array_info()
|
||||||
node.elem_type = array_info.elem_type
|
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) {
|
return if c.expected_type.has_flag(.shared_f) {
|
||||||
c.expected_type.clear_flag(.shared_f).deref()
|
c.expected_type.clear_flag(.shared_f).deref()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
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 | }
|
26 | }
|
||||||
27 | // should be an checker error:
|
27 | // should be an checker error:
|
||||||
28 | if x := return_string() {
|
28 | if x := return_string() {
|
||||||
|
|
|
@ -132,11 +132,19 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||||
var_name = g.new_tmp_var()
|
var_name = g.new_tmp_var()
|
||||||
guard_vars[i] = var_name // for `else`
|
guard_vars[i] = var_name // for `else`
|
||||||
g.tmp_count--
|
g.tmp_count--
|
||||||
|
if branch.cond.expr_type.has_flag(.optional) {
|
||||||
g.writeln('if (${var_name}.state == 0) {')
|
g.writeln('if (${var_name}.state == 0) {')
|
||||||
|
} else if branch.cond.expr_type.has_flag(.result) {
|
||||||
|
g.writeln('if (!${var_name}.is_error) {')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.write('if ($var_name = ')
|
g.write('if ($var_name = ')
|
||||||
g.expr(branch.cond.expr)
|
g.expr(branch.cond.expr)
|
||||||
|
if branch.cond.expr_type.has_flag(.optional) {
|
||||||
g.writeln(', ${var_name}.state == 0) {')
|
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 != '_' {
|
if short_opt || branch.cond.vars[0].name != '_' {
|
||||||
base_type := g.base_type(branch.cond.expr_type)
|
base_type := g.base_type(branch.cond.expr_type)
|
||||||
|
|
|
@ -81,3 +81,16 @@ fn return_reference_type(path string) !&string {
|
||||||
str := ''
|
str := ''
|
||||||
return &str
|
return &str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read() !string {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_results_if_guard() {
|
||||||
|
if fcontent := read() {
|
||||||
|
assert fcontent == ''
|
||||||
|
assert '$fcontent' == ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue