mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
This commit is contained in:
parent
fda0af482f
commit
b51dfcfe7d
@ -71,16 +71,18 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
||||
} else {
|
||||
node.expected_type
|
||||
}
|
||||
expr_type := if stmt.expr is ast.CallExpr {
|
||||
expr_type := c.unwrap_generic(if stmt.expr is ast.CallExpr {
|
||||
stmt.typ
|
||||
} else {
|
||||
c.expr(mut stmt.expr)
|
||||
}
|
||||
})
|
||||
unwrapped_expected_type := c.unwrap_generic(node.expected_type)
|
||||
stmt.typ = expr_type
|
||||
if first_iteration {
|
||||
if node.expected_type.has_option_or_result()
|
||||
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return] {
|
||||
c.check_match_branch_last_stmt(stmt, node.expected_type, expr_type)
|
||||
if unwrapped_expected_type.has_option_or_result()
|
||||
|| c.table.type_kind(unwrapped_expected_type) in [.sum_type, .multi_return] {
|
||||
c.check_match_branch_last_stmt(stmt, unwrapped_expected_type,
|
||||
expr_type)
|
||||
ret_type = node.expected_type
|
||||
} else {
|
||||
ret_type = expr_type
|
||||
@ -105,10 +107,9 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
||||
}
|
||||
} else {
|
||||
if ret_type.idx() != expr_type.idx() {
|
||||
if node.expected_type.has_option_or_result()
|
||||
if unwrapped_expected_type.has_option_or_result()
|
||||
&& c.table.sym(stmt.typ).kind == .struct
|
||||
&& (c.table.sym(ret_type).kind != .sum_type
|
||||
|| !c.check_types(expr_type, ret_type))
|
||||
&& !c.check_types(expr_type, c.unwrap_generic(ret_type))
|
||||
&& c.type_implements(stmt.typ, ast.error_type, node.pos) {
|
||||
stmt.expr = ast.CastExpr{
|
||||
expr: stmt.expr
|
||||
@ -119,7 +120,8 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
||||
}
|
||||
stmt.typ = ast.error_type
|
||||
} else {
|
||||
c.check_match_branch_last_stmt(stmt, ret_type, expr_type)
|
||||
c.check_match_branch_last_stmt(stmt, c.unwrap_generic(ret_type),
|
||||
expr_type)
|
||||
if ret_type.is_number() && expr_type.is_number() && !c.inside_return {
|
||||
ret_type = c.promote_num(ret_type, expr_type)
|
||||
}
|
||||
@ -130,13 +132,13 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
||||
stmt_sym := c.table.sym(stmt.typ)
|
||||
if ret_sym.kind !in [.sum_type, .interface]
|
||||
&& stmt_sym.kind in [.sum_type, .interface] {
|
||||
c.error('return type mismatch, it should be `${ret_sym.name}`',
|
||||
c.error('return type mismatch, it should be `${ret_sym.name}`, but it is instead `${c.table.type_to_str(expr_type)}`',
|
||||
stmt.pos)
|
||||
}
|
||||
if ret_type.nr_muls() != stmt.typ.nr_muls()
|
||||
&& stmt.typ.idx() !in [ast.voidptr_type_idx, ast.nil_type_idx] {
|
||||
type_name := '&'.repeat(ret_type.nr_muls()) + ret_sym.name
|
||||
c.error('return type mismatch, it should be `${type_name}`',
|
||||
c.error('return type mismatch, it should be `${type_name}`, but it is instead `${c.table.type_to_str(expr_type)}`',
|
||||
stmt.pos)
|
||||
}
|
||||
}
|
||||
@ -279,7 +281,8 @@ fn (mut c Checker) check_match_branch_last_stmt(last_stmt ast.ExprStmt, ret_type
|
||||
return
|
||||
}
|
||||
}
|
||||
c.error('return type mismatch, it should be `${ret_sym.name}`', last_stmt.pos)
|
||||
c.error('return type mismatch, it should be `${ret_sym.name}`, but it is instead `${c.table.type_to_str(expr_type)}`',
|
||||
last_stmt.pos)
|
||||
}
|
||||
} else if expr_type == ast.void_type && ret_type.idx() == ast.void_type_idx
|
||||
&& ret_type.has_option_or_result() {
|
||||
|
7
vlib/v/checker/tests/match_generic_case_err.out
Normal file
7
vlib/v/checker/tests/match_generic_case_err.out
Normal file
@ -0,0 +1,7 @@
|
||||
vlib/v/checker/tests/match_generic_case_err.vv:16:4: error: return type mismatch, it should be `int`, but it is instead `string`
|
||||
14 | }
|
||||
15 | 'int' {
|
||||
16 | v
|
||||
| ^
|
||||
17 | }
|
||||
18 | else {
|
22
vlib/v/checker/tests/match_generic_case_err.vv
Normal file
22
vlib/v/checker/tests/match_generic_case_err.vv
Normal file
@ -0,0 +1,22 @@
|
||||
module main
|
||||
|
||||
import strconv
|
||||
|
||||
fn main() {
|
||||
println(to_int('1'))
|
||||
println(to_int(1))
|
||||
}
|
||||
|
||||
fn to_int[T](v T) i64 {
|
||||
return match typeof(v).name {
|
||||
'string' {
|
||||
strconv.atoi(v) or { 0 }
|
||||
}
|
||||
'int' {
|
||||
v
|
||||
}
|
||||
else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
@ -5,35 +5,35 @@ vlib/v/checker/tests/match_return_mismatch_type_err.vv:27:6: warning: cannot ass
|
||||
| ^
|
||||
28 | string { &any }
|
||||
29 | else { &variable }
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:4:10: error: return type mismatch, it should be `string`
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:4:10: error: return type mismatch, it should be `string`, but it is instead `int literal`
|
||||
2 | a := match 1 {
|
||||
3 | 1 { 'aa' }
|
||||
4 | else { 22 }
|
||||
| ~~
|
||||
5 | }
|
||||
6 | println(a)
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:18:10: error: return type mismatch, it should be `&string`
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:18:10: error: return type mismatch, it should be `&string`, but it is instead `string`
|
||||
16 | _ = match any {
|
||||
17 | string { &any }
|
||||
18 | else { variable }
|
||||
| ~~~~~~~~
|
||||
19 | }
|
||||
20 |
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:23:10: error: return type mismatch, it should be `string`
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:23:10: error: return type mismatch, it should be `string`, but it is instead `&string`
|
||||
21 | _ = match any {
|
||||
22 | string { any }
|
||||
23 | else { &variable }
|
||||
| ^
|
||||
24 | }
|
||||
25 |
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:43:10: error: return type mismatch, it should be `&string`
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:43:10: error: return type mismatch, it should be `&string`, but it is instead `string`
|
||||
41 | _ = match any {
|
||||
42 | string { &any }
|
||||
43 | else { variable }
|
||||
| ~~~~~~~~
|
||||
44 | }
|
||||
45 |
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:48:10: error: return type mismatch, it should be `string`
|
||||
vlib/v/checker/tests/match_return_mismatch_type_err.vv:48:10: error: return type mismatch, it should be `string`, but it is instead `&string`
|
||||
46 | _ = match any {
|
||||
47 | string { any }
|
||||
48 | else { &variable }
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/match_return_sumtype_mismatch_err.vv:15:11: error: return type mismatch, it should be `Myt`
|
||||
vlib/v/checker/tests/match_return_sumtype_mismatch_err.vv:15:11: error: return type mismatch, it should be `Myt`, but it is instead `rune`
|
||||
13 | return match b {
|
||||
14 | true { St('TRUE') }
|
||||
15 | false { `F` }
|
||||
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/return_match_expr_type_mismatch.vv:18:16: error: return type mismatch, it should be `SomeTuple`
|
||||
vlib/v/checker/tests/return_match_expr_type_mismatch.vv:18:16: error: return type mismatch, it should be `SomeTuple`, but it is instead `Poss1`
|
||||
16 | fn get_file(item PossOwner) ?SomeTuple {
|
||||
17 | return match item.pos {
|
||||
18 | Poss1 { item.pos }
|
||||
|
24
vlib/v/tests/generics/generic_match_expr_test.v
Normal file
24
vlib/v/tests/generics/generic_match_expr_test.v
Normal file
@ -0,0 +1,24 @@
|
||||
struct Foo[T] {
|
||||
a T
|
||||
}
|
||||
|
||||
fn r[T]() Foo[T] {
|
||||
return Foo[T]{}
|
||||
}
|
||||
|
||||
fn t[T](v T) !Foo[T] {
|
||||
return match typeof(v).name {
|
||||
'string' {
|
||||
r[T]()
|
||||
}
|
||||
else {
|
||||
r[T]()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
t(1)!
|
||||
t('')!
|
||||
assert true
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user