mirror of
https://github.com/vlang/v.git
synced 2025-08-04 02:07:28 -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 {
|
} else {
|
||||||
node.expected_type
|
node.expected_type
|
||||||
}
|
}
|
||||||
expr_type := if stmt.expr is ast.CallExpr {
|
expr_type := c.unwrap_generic(if stmt.expr is ast.CallExpr {
|
||||||
stmt.typ
|
stmt.typ
|
||||||
} else {
|
} else {
|
||||||
c.expr(mut stmt.expr)
|
c.expr(mut stmt.expr)
|
||||||
}
|
})
|
||||||
|
unwrapped_expected_type := c.unwrap_generic(node.expected_type)
|
||||||
stmt.typ = expr_type
|
stmt.typ = expr_type
|
||||||
if first_iteration {
|
if first_iteration {
|
||||||
if node.expected_type.has_option_or_result()
|
if unwrapped_expected_type.has_option_or_result()
|
||||||
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return] {
|
|| c.table.type_kind(unwrapped_expected_type) in [.sum_type, .multi_return] {
|
||||||
c.check_match_branch_last_stmt(stmt, node.expected_type, expr_type)
|
c.check_match_branch_last_stmt(stmt, unwrapped_expected_type,
|
||||||
|
expr_type)
|
||||||
ret_type = node.expected_type
|
ret_type = node.expected_type
|
||||||
} else {
|
} else {
|
||||||
ret_type = expr_type
|
ret_type = expr_type
|
||||||
@ -105,10 +107,9 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ret_type.idx() != expr_type.idx() {
|
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(stmt.typ).kind == .struct
|
||||||
&& (c.table.sym(ret_type).kind != .sum_type
|
&& !c.check_types(expr_type, c.unwrap_generic(ret_type))
|
||||||
|| !c.check_types(expr_type, ret_type))
|
|
||||||
&& c.type_implements(stmt.typ, ast.error_type, node.pos) {
|
&& c.type_implements(stmt.typ, ast.error_type, node.pos) {
|
||||||
stmt.expr = ast.CastExpr{
|
stmt.expr = ast.CastExpr{
|
||||||
expr: stmt.expr
|
expr: stmt.expr
|
||||||
@ -119,7 +120,8 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
stmt.typ = ast.error_type
|
stmt.typ = ast.error_type
|
||||||
} else {
|
} 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 {
|
if ret_type.is_number() && expr_type.is_number() && !c.inside_return {
|
||||||
ret_type = c.promote_num(ret_type, expr_type)
|
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)
|
stmt_sym := c.table.sym(stmt.typ)
|
||||||
if ret_sym.kind !in [.sum_type, .interface]
|
if ret_sym.kind !in [.sum_type, .interface]
|
||||||
&& stmt_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)
|
stmt.pos)
|
||||||
}
|
}
|
||||||
if ret_type.nr_muls() != stmt.typ.nr_muls()
|
if ret_type.nr_muls() != stmt.typ.nr_muls()
|
||||||
&& stmt.typ.idx() !in [ast.voidptr_type_idx, ast.nil_type_idx] {
|
&& stmt.typ.idx() !in [ast.voidptr_type_idx, ast.nil_type_idx] {
|
||||||
type_name := '&'.repeat(ret_type.nr_muls()) + ret_sym.name
|
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)
|
stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,7 +281,8 @@ fn (mut c Checker) check_match_branch_last_stmt(last_stmt ast.ExprStmt, ret_type
|
|||||||
return
|
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
|
} else if expr_type == ast.void_type && ret_type.idx() == ast.void_type_idx
|
||||||
&& ret_type.has_option_or_result() {
|
&& 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 }
|
28 | string { &any }
|
||||||
29 | else { &variable }
|
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 {
|
2 | a := match 1 {
|
||||||
3 | 1 { 'aa' }
|
3 | 1 { 'aa' }
|
||||||
4 | else { 22 }
|
4 | else { 22 }
|
||||||
| ~~
|
| ~~
|
||||||
5 | }
|
5 | }
|
||||||
6 | println(a)
|
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 {
|
16 | _ = match any {
|
||||||
17 | string { &any }
|
17 | string { &any }
|
||||||
18 | else { variable }
|
18 | else { variable }
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
19 | }
|
19 | }
|
||||||
20 |
|
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 {
|
21 | _ = match any {
|
||||||
22 | string { any }
|
22 | string { any }
|
||||||
23 | else { &variable }
|
23 | else { &variable }
|
||||||
| ^
|
| ^
|
||||||
24 | }
|
24 | }
|
||||||
25 |
|
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 {
|
41 | _ = match any {
|
||||||
42 | string { &any }
|
42 | string { &any }
|
||||||
43 | else { variable }
|
43 | else { variable }
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
44 | }
|
44 | }
|
||||||
45 |
|
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 {
|
46 | _ = match any {
|
||||||
47 | string { any }
|
47 | string { any }
|
||||||
48 | else { &variable }
|
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 {
|
13 | return match b {
|
||||||
14 | true { St('TRUE') }
|
14 | true { St('TRUE') }
|
||||||
15 | false { `F` }
|
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 {
|
16 | fn get_file(item PossOwner) ?SomeTuple {
|
||||||
17 | return match item.pos {
|
17 | return match item.pos {
|
||||||
18 | Poss1 { 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