mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
parent
e51f0be6db
commit
adc3b25f52
|
@ -179,11 +179,11 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
c.smartcast_cond_pos = token.Pos{}
|
||||
}
|
||||
if expr_required {
|
||||
if branch.stmts.len > 0 && branch.stmts.last() is ast.ExprStmt {
|
||||
mut last_expr := branch.stmts.last() as ast.ExprStmt
|
||||
expr := last_expr.expr
|
||||
if expr is ast.ConcatExpr {
|
||||
for val in expr.vals {
|
||||
if branch.stmts.len > 0 {
|
||||
mut stmt := branch.stmts.last()
|
||||
if mut stmt is ast.ExprStmt {
|
||||
if mut stmt.expr is ast.ConcatExpr {
|
||||
for val in stmt.expr.vals {
|
||||
c.check_expr_opt_call(val, c.expr(val))
|
||||
}
|
||||
}
|
||||
|
@ -206,43 +206,43 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
}
|
||||
continue
|
||||
}
|
||||
last_expr.typ = c.expr(last_expr.expr)
|
||||
stmt.typ = c.expr(stmt.expr)
|
||||
if c.table.type_kind(c.expected_type) == .multi_return
|
||||
&& c.table.type_kind(last_expr.typ) == .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 last_expr.typ == ast.void_type && !is_noreturn_callexpr(last_expr.expr)
|
||||
if stmt.typ == ast.void_type && !is_noreturn_callexpr(stmt.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)
|
||||
stmt.pos)
|
||||
continue
|
||||
}
|
||||
if !c.check_types(last_expr.typ, node.typ) {
|
||||
if !c.check_types(stmt.typ, node.typ) {
|
||||
if node.typ == ast.void_type {
|
||||
// first branch of if expression
|
||||
node.is_expr = true
|
||||
node.typ = last_expr.typ
|
||||
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 last_expr.typ.is_int() || last_expr.typ.is_float() {
|
||||
node.typ = last_expr.typ
|
||||
if stmt.typ.is_int() || stmt.typ.is_float() {
|
||||
node.typ = stmt.typ
|
||||
continue
|
||||
}
|
||||
} else { // node.typ == float_literal
|
||||
if last_expr.typ.is_float() {
|
||||
node.typ = last_expr.typ
|
||||
if stmt.typ.is_float() {
|
||||
node.typ = stmt.typ
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if last_expr.typ in [ast.float_literal_type, ast.int_literal_type] {
|
||||
if last_expr.typ == ast.int_literal_type {
|
||||
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
|
||||
}
|
||||
|
@ -256,16 +256,20 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
node.typ = former_expected_type
|
||||
continue
|
||||
}
|
||||
if is_noreturn_callexpr(last_expr.expr) {
|
||||
if is_noreturn_callexpr(stmt.expr) {
|
||||
continue
|
||||
}
|
||||
c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(last_expr.typ)}`',
|
||||
c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(stmt.typ)}`',
|
||||
node.pos)
|
||||
}
|
||||
} else if !node.is_comptime {
|
||||
c.error('`$if_kind` expression requires an expression as the last statement of every branch',
|
||||
branch.pos)
|
||||
}
|
||||
} else if !node.is_comptime {
|
||||
c.error('`$if_kind` expression requires an expression as the last statement of every branch',
|
||||
branch.pos)
|
||||
}
|
||||
}
|
||||
// Also check for returns inside a comp.if's statements, even if its contents aren't parsed
|
||||
if has_return := c.has_return(branch.stmts) {
|
||||
|
|
|
@ -139,10 +139,19 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
|||
needs_tmp_var := g.need_tmp_var_in_if(node)
|
||||
tmp := if needs_tmp_var { g.new_tmp_var() } else { '' }
|
||||
mut cur_line := ''
|
||||
mut raw_state := false
|
||||
if needs_tmp_var {
|
||||
if node.typ.has_flag(.optional) {
|
||||
raw_state = g.inside_if_optional
|
||||
defer {
|
||||
g.inside_if_optional = raw_state
|
||||
}
|
||||
g.inside_if_optional = true
|
||||
} 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
|
||||
}
|
||||
styp := g.typ(node.typ)
|
||||
|
@ -325,9 +334,4 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
|||
g.empty_line = false
|
||||
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
|
||||
}
|
Loading…
Reference in New Issue
Block a user