mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: check type mismatch of return match expr (#16019)
This commit is contained in:
parent
89eb8358cf
commit
8f3f717736
@ -64,30 +64,13 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
|||||||
if node.is_expr && (node.expected_type.has_flag(.optional)
|
if node.is_expr && (node.expected_type.has_flag(.optional)
|
||||||
|| node.expected_type.has_flag(.result)
|
|| node.expected_type.has_flag(.result)
|
||||||
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return]) {
|
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return]) {
|
||||||
|
c.check_match_branch_last_stmt(stmt, node.expected_type, expr_type)
|
||||||
ret_type = node.expected_type
|
ret_type = node.expected_type
|
||||||
} else {
|
} else {
|
||||||
ret_type = expr_type
|
ret_type = expr_type
|
||||||
}
|
}
|
||||||
} else if node.is_expr && ret_type.idx() != expr_type.idx() {
|
} else if node.is_expr && ret_type.idx() != expr_type.idx() {
|
||||||
if !c.check_types(ret_type, expr_type) && !c.check_types(expr_type, ret_type) {
|
c.check_match_branch_last_stmt(stmt, ret_type, expr_type)
|
||||||
ret_sym := c.table.sym(ret_type)
|
|
||||||
is_noreturn := is_noreturn_callexpr(stmt.expr)
|
|
||||||
if !(node.is_expr && ret_sym.kind == .sum_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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if node.is_expr && ret_type != ast.void_type {
|
if node.is_expr && ret_type != ast.void_type {
|
||||||
@ -137,6 +120,25 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
|||||||
return ret_type
|
return ret_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) check_match_branch_last_stmt(last_stmt ast.ExprStmt, ret_type ast.Type, expr_type ast.Type) {
|
||||||
|
if !c.check_types(ret_type, expr_type) && !c.check_types(expr_type, ret_type) {
|
||||||
|
ret_sym := c.table.sym(ret_type)
|
||||||
|
is_noreturn := is_noreturn_callexpr(last_stmt.expr)
|
||||||
|
if !(ret_sym.kind == .sum_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 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.error('return type mismatch, it should be `$ret_sym.name`', last_stmt.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSymbol) {
|
fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSymbol) {
|
||||||
// branch_exprs is a histogram of how many times
|
// branch_exprs is a histogram of how many times
|
||||||
// an expr was used in the match
|
// an expr was used in the match
|
||||||
|
7
vlib/v/checker/tests/return_match_expr_type_mismatch.out
Normal file
7
vlib/v/checker/tests/return_match_expr_type_mismatch.out
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
vlib/v/checker/tests/return_match_expr_type_mismatch.vv:18:16: error: return type mismatch, it should be `SomeTuple`
|
||||||
|
16 | fn get_file(item PossOwner) ?SomeTuple {
|
||||||
|
17 | return match item.pos {
|
||||||
|
18 | Poss1 { item.pos }
|
||||||
|
| ~~~
|
||||||
|
19 | else { error('not poss1') }
|
||||||
|
20 | }
|
34
vlib/v/checker/tests/return_match_expr_type_mismatch.vv
Normal file
34
vlib/v/checker/tests/return_match_expr_type_mismatch.vv
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
struct Poss1 {}
|
||||||
|
|
||||||
|
struct Poss2 {}
|
||||||
|
|
||||||
|
type Possibilities = Poss1 | Poss2
|
||||||
|
|
||||||
|
struct PossOwner {
|
||||||
|
pos Possibilities
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SomeTuple {
|
||||||
|
p PossOwner
|
||||||
|
f Poss1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_file(item PossOwner) ?SomeTuple {
|
||||||
|
return match item.pos {
|
||||||
|
Poss1 { item.pos }
|
||||||
|
else { error('not poss1') }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
item := PossOwner{
|
||||||
|
pos: Poss1{}
|
||||||
|
}
|
||||||
|
|
||||||
|
r := get_file(item) or {
|
||||||
|
println('err=$err')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println('got $r')
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user