mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
@@ -179,88 +179,92 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||||||
c.smartcast_cond_pos = token.Pos{}
|
c.smartcast_cond_pos = token.Pos{}
|
||||||
}
|
}
|
||||||
if expr_required {
|
if expr_required {
|
||||||
if branch.stmts.len > 0 && branch.stmts.last() is ast.ExprStmt {
|
if branch.stmts.len > 0 {
|
||||||
mut last_expr := branch.stmts.last() as ast.ExprStmt
|
mut stmt := branch.stmts.last()
|
||||||
expr := last_expr.expr
|
if mut stmt is ast.ExprStmt {
|
||||||
if expr is ast.ConcatExpr {
|
if mut stmt.expr is ast.ConcatExpr {
|
||||||
for val in expr.vals {
|
for val in stmt.expr.vals {
|
||||||
c.check_expr_opt_call(val, c.expr(val))
|
c.check_expr_opt_call(val, c.expr(val))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
c.expected_type = former_expected_type
|
||||||
c.expected_type = former_expected_type
|
if c.table.type_kind(c.expected_type) == .sum_type
|
||||||
if c.table.type_kind(c.expected_type) == .sum_type
|
&& c.table.is_sumtype_or_in_variant(c.expected_type, node.typ) {
|
||||||
&& c.table.is_sumtype_or_in_variant(c.expected_type, node.typ) {
|
|
||||||
node.is_expr = true
|
|
||||||
node.typ = c.expected_type
|
|
||||||
}
|
|
||||||
if c.expected_type.has_flag(.optional) || c.expected_type.has_flag(.result) {
|
|
||||||
if node.typ == ast.void_type {
|
|
||||||
node.is_expr = true
|
node.is_expr = true
|
||||||
node.typ = c.expected_type
|
node.typ = c.expected_type
|
||||||
}
|
}
|
||||||
}
|
if c.expected_type.has_flag(.optional) || c.expected_type.has_flag(.result) {
|
||||||
if c.expected_type.has_flag(.generic) {
|
if node.typ == ast.void_type {
|
||||||
if node.typ == ast.void_type {
|
node.is_expr = true
|
||||||
node.is_expr = true
|
node.typ = c.expected_type
|
||||||
node.typ = c.unwrap_generic(c.expected_type)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
last_expr.typ = c.expr(last_expr.expr)
|
|
||||||
if c.table.type_kind(c.expected_type) == .multi_return
|
|
||||||
&& c.table.type_kind(last_expr.typ) == .multi_return {
|
|
||||||
if node.typ == ast.void_type {
|
|
||||||
node.is_expr = true
|
|
||||||
node.typ = c.expected_type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if last_expr.typ == ast.void_type && !is_noreturn_callexpr(last_expr.expr)
|
|
||||||
&& !c.skip_flags {
|
|
||||||
// cannot return void type and use it as expr in any circumstances
|
|
||||||
// (e.g. argument expression, variable declaration / assignment)
|
|
||||||
c.error('the final expression in `if` or `match`, must have a value of a non-void type',
|
|
||||||
last_expr.pos)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !c.check_types(last_expr.typ, node.typ) {
|
|
||||||
if node.typ == ast.void_type {
|
|
||||||
// first branch of if expression
|
|
||||||
node.is_expr = true
|
|
||||||
node.typ = last_expr.typ
|
|
||||||
continue
|
|
||||||
} else if node.typ in [ast.float_literal_type, ast.int_literal_type] {
|
|
||||||
if node.typ == ast.int_literal_type {
|
|
||||||
if last_expr.typ.is_int() || last_expr.typ.is_float() {
|
|
||||||
node.typ = last_expr.typ
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else { // node.typ == float_literal
|
|
||||||
if last_expr.typ.is_float() {
|
|
||||||
node.typ = last_expr.typ
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if last_expr.typ in [ast.float_literal_type, ast.int_literal_type] {
|
if c.expected_type.has_flag(.generic) {
|
||||||
if last_expr.typ == ast.int_literal_type {
|
if node.typ == ast.void_type {
|
||||||
if node.typ.is_int() || node.typ.is_float() {
|
node.is_expr = true
|
||||||
continue
|
node.typ = c.unwrap_generic(c.expected_type)
|
||||||
}
|
}
|
||||||
} else { // expr_type == float_literal
|
continue
|
||||||
if node.typ.is_float() {
|
}
|
||||||
continue
|
stmt.typ = c.expr(stmt.expr)
|
||||||
}
|
if c.table.type_kind(c.expected_type) == .multi_return
|
||||||
|
&& c.table.type_kind(stmt.typ) == .multi_return {
|
||||||
|
if node.typ == ast.void_type {
|
||||||
|
node.is_expr = true
|
||||||
|
node.typ = c.expected_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node.is_expr && c.table.sym(former_expected_type).kind == .sum_type {
|
if stmt.typ == ast.void_type && !is_noreturn_callexpr(stmt.expr)
|
||||||
node.typ = former_expected_type
|
&& !c.skip_flags {
|
||||||
|
// cannot return void type and use it as expr in any circumstances
|
||||||
|
// (e.g. argument expression, variable declaration / assignment)
|
||||||
|
c.error('the final expression in `if` or `match`, must have a value of a non-void type',
|
||||||
|
stmt.pos)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if is_noreturn_callexpr(last_expr.expr) {
|
if !c.check_types(stmt.typ, node.typ) {
|
||||||
continue
|
if node.typ == ast.void_type {
|
||||||
|
// first branch of if expression
|
||||||
|
node.is_expr = true
|
||||||
|
node.typ = stmt.typ
|
||||||
|
continue
|
||||||
|
} else if node.typ in [ast.float_literal_type, ast.int_literal_type] {
|
||||||
|
if node.typ == ast.int_literal_type {
|
||||||
|
if stmt.typ.is_int() || stmt.typ.is_float() {
|
||||||
|
node.typ = stmt.typ
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else { // node.typ == float_literal
|
||||||
|
if stmt.typ.is_float() {
|
||||||
|
node.typ = stmt.typ
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stmt.typ in [ast.float_literal_type, ast.int_literal_type] {
|
||||||
|
if stmt.typ == ast.int_literal_type {
|
||||||
|
if node.typ.is_int() || node.typ.is_float() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else { // expr_type == float_literal
|
||||||
|
if node.typ.is_float() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.is_expr && c.table.sym(former_expected_type).kind == .sum_type {
|
||||||
|
node.typ = former_expected_type
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if is_noreturn_callexpr(stmt.expr) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(stmt.typ)}`',
|
||||||
|
node.pos)
|
||||||
}
|
}
|
||||||
c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(last_expr.typ)}`',
|
} else if !node.is_comptime {
|
||||||
node.pos)
|
c.error('`$if_kind` expression requires an expression as the last statement of every branch',
|
||||||
|
branch.pos)
|
||||||
}
|
}
|
||||||
} else if !node.is_comptime {
|
} else if !node.is_comptime {
|
||||||
c.error('`$if_kind` expression requires an expression as the last statement of every branch',
|
c.error('`$if_kind` expression requires an expression as the last statement of every branch',
|
||||||
|
|||||||
@@ -139,10 +139,19 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
|||||||
needs_tmp_var := g.need_tmp_var_in_if(node)
|
needs_tmp_var := g.need_tmp_var_in_if(node)
|
||||||
tmp := if needs_tmp_var { g.new_tmp_var() } else { '' }
|
tmp := if needs_tmp_var { g.new_tmp_var() } else { '' }
|
||||||
mut cur_line := ''
|
mut cur_line := ''
|
||||||
|
mut raw_state := false
|
||||||
if needs_tmp_var {
|
if needs_tmp_var {
|
||||||
if node.typ.has_flag(.optional) {
|
if node.typ.has_flag(.optional) {
|
||||||
|
raw_state = g.inside_if_optional
|
||||||
|
defer {
|
||||||
|
g.inside_if_optional = raw_state
|
||||||
|
}
|
||||||
g.inside_if_optional = true
|
g.inside_if_optional = true
|
||||||
} else if node.typ.has_flag(.result) {
|
} else if node.typ.has_flag(.result) {
|
||||||
|
raw_state = g.inside_if_result
|
||||||
|
defer {
|
||||||
|
g.inside_if_result = raw_state
|
||||||
|
}
|
||||||
g.inside_if_result = true
|
g.inside_if_result = true
|
||||||
}
|
}
|
||||||
styp := g.typ(node.typ)
|
styp := g.typ(node.typ)
|
||||||
@@ -325,9 +334,4 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
|||||||
g.empty_line = false
|
g.empty_line = false
|
||||||
g.write('$cur_line $tmp')
|
g.write('$cur_line $tmp')
|
||||||
}
|
}
|
||||||
if node.typ.has_flag(.optional) {
|
|
||||||
g.inside_if_optional = false
|
|
||||||
} else if node.typ.has_flag(.result) {
|
|
||||||
g.inside_if_result = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
57
vlib/v/tests/if_expr_nested_with_optional_result_test.v
Normal file
57
vlib/v/tests/if_expr_nested_with_optional_result_test.v
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// optional
|
||||||
|
pub fn foo1() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bar1(i int) ?int {
|
||||||
|
if i < 0 {
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
return if i == 0 {
|
||||||
|
if foo1() {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// result
|
||||||
|
pub fn foo2() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bar2(i int) !int {
|
||||||
|
if i < 0 {
|
||||||
|
return error('')
|
||||||
|
}
|
||||||
|
return if i == 0 {
|
||||||
|
if foo2() {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_expr_nested_with_optional_result() {
|
||||||
|
ret11 := bar1(0) or { 0 }
|
||||||
|
println(ret11)
|
||||||
|
assert ret11 == 2
|
||||||
|
|
||||||
|
ret12 := bar1(1) or { 0 }
|
||||||
|
println(ret12)
|
||||||
|
assert ret12 == 3
|
||||||
|
|
||||||
|
ret21 := bar2(0) or { 0 }
|
||||||
|
println(ret21)
|
||||||
|
assert ret21 == 2
|
||||||
|
|
||||||
|
ret22 := bar2(1) or { 0 }
|
||||||
|
println(ret22)
|
||||||
|
assert ret22 == 3
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user