Skip to content

Commit 95f0093

Browse files
authored
checker: fix MatchExpr type inferring, when none is used (fix #23831) (#23833)
1 parent f7e062c commit 95f0093

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

vlib/v/checker/match.v

+11-4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
4141
mut ret_type := ast.void_type
4242
mut nbranches_with_return := 0
4343
mut nbranches_without_return := 0
44+
mut must_be_option := false
4445
for mut branch in node.branches {
4546
if node.is_expr {
4647
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
@@ -77,6 +78,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
7778
c.expr(mut stmt.expr)
7879
})
7980
unwrapped_expected_type := c.unwrap_generic(node.expected_type)
81+
must_be_option = must_be_option || expr_type == ast.none_type
8082
stmt.typ = expr_type
8183
if first_iteration {
8284
if unwrapped_expected_type.has_option_or_result()
@@ -127,6 +129,9 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
127129
}
128130
}
129131
}
132+
if must_be_option && ret_type == ast.none_type && expr_type != ret_type {
133+
ret_type = expr_type.set_flag(.option)
134+
}
130135
if stmt.typ != ast.error_type && !is_noreturn_callexpr(stmt.expr) {
131136
ret_sym := c.table.sym(ret_type)
132137
stmt_sym := c.table.sym(stmt.typ)
@@ -249,7 +254,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
249254
c.error('invalid match expression, must supply at least one value other than `none`',
250255
node.pos)
251256
}
252-
node.return_type = ret_type
257+
node.return_type = if must_be_option { ret_type.set_flag(.option) } else { ret_type }
253258
cond_var := c.get_base_name(&node.cond)
254259
if cond_var != '' {
255260
mut cond_is_auto_heap := false
@@ -268,7 +273,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
268273
}
269274
}
270275
}
271-
return ret_type
276+
return node.return_type
272277
}
273278

274279
fn (mut c Checker) check_match_branch_last_stmt(last_stmt ast.ExprStmt, ret_type ast.Type, expr_type ast.Type) {
@@ -285,8 +290,10 @@ fn (mut c Checker) check_match_branch_last_stmt(last_stmt ast.ExprStmt, ret_type
285290
return
286291
}
287292
}
288-
c.error('return type mismatch, it should be `${ret_sym.name}`, but it is instead `${c.table.type_to_str(expr_type)}`',
289-
last_stmt.pos)
293+
if expr_type != ast.none_type && ret_type != ast.none_type {
294+
c.error('return type mismatch, it should be `${ret_sym.name}`, but it is instead `${c.table.type_to_str(expr_type)}`',
295+
last_stmt.pos)
296+
}
290297
}
291298
} else if expr_type == ast.void_type && ret_type.idx() == ast.void_type_idx
292299
&& ret_type.has_option_or_result() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
fn test_main() {
2+
a := match 1 {
3+
0 { none }
4+
else { 1 }
5+
}
6+
assert '${a}' == 'Option(1)'
7+
8+
b := match 2 {
9+
0 { none }
10+
2 { none }
11+
else { 1 }
12+
}
13+
assert '${b}' == 'Option(none)'
14+
15+
c := match 2 {
16+
0 { 1 }
17+
2 { 2 }
18+
else { none }
19+
}
20+
assert '${c}' == 'Option(2)'
21+
}

0 commit comments

Comments
 (0)