checker: fix error for fn with multi return (#14095)

yuyi 2022-04-20 18:09:40 +08:00 committed by Jef Roosens
parent f7dbbba7ae
commit 9abf3a62c0
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
3 changed files with 74 additions and 1 deletions

View File

@ -173,6 +173,13 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.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 !c.check_types(last_expr.typ, node.typ) {
if node.typ == ast.void_type {
// first branch of if expression
@ -210,6 +217,15 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
if is_noreturn_callexpr(last_expr.expr) {
continue
}
node_sym := c.table.sym(node.typ)
last_sym := c.table.sym(last_expr.typ)
if node_sym.kind == .multi_return && last_sym.kind == .multi_return {
node_types := node_sym.mr_info().types
last_types := last_sym.mr_info().types.map(ast.mktyp(it))
if node_types == last_types {
continue
}
}
c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(last_expr.typ)}`',
node.pos)

View File

@ -72,7 +72,7 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
expr_type := c.expr(stmt.expr)
if first_iteration {
if node.is_expr && (node.expected_type.has_flag(.optional)
|| c.table.type_kind(node.expected_type) == .sum_type) {
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return]) {
ret_type = node.expected_type
} else {
ret_type = expr_type
@ -86,6 +86,14 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
&& (ret_type.has_flag(.generic)
|| c.table.is_sumtype_or_in_variant(ret_type, expr_type)))
&& !is_noreturn {
expr_sym := c.table.sym(expr_type)
if expr_sym.kind == .multi_return && ret_sym.kind == .multi_return {
ret_types := ret_sym.mr_info().types
expr_types := expr_sym.mr_info().types.map(ast.mktyp(it))
if expr_types == ret_types {
continue
}
}
c.error('return type mismatch, it should be `$ret_sym.name`',
stmt.expr.pos())
}

View File

@ -0,0 +1,49 @@
fn multret1(i int, j int) (int, int) {
return if i > j { i, 10 } else { 10, j }
}
fn multret2(i int, j int) (int, int) {
return match i > j {
true { i, 10 }
false { 10, j }
}
}
fn multret3(i int, j int) (int, int) {
if i > j {
return i, 10
} else {
return 10, j
}
}
fn multret4(i int, j int) (int, int) {
match i > j {
true { return i, 10 }
false { return 10, j }
}
}
fn test_fn_multi_return() {
mut a, mut b := 0, 0
println(multret1(3, 14))
a, b = multret1(3, 14)
assert a == 10
assert b == 14
println(multret2(3, 14))
a, b = multret2(3, 14)
assert a == 10
assert b == 14
println(multret3(3, 14))
a, b = multret3(3, 14)
assert a == 10
assert b == 14
println(multret4(3, 14))
a, b = multret4(3, 14)
assert a == 10
assert b == 14
}