checker: fix match expr with enum type value (#13683)

pull/13685/head
yuyi 2022-03-08 15:50:17 +08:00 committed by GitHub
parent 17fcc788f2
commit cea3149369
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 20 deletions

View File

@ -57,25 +57,26 @@ fn all_valid_comptime_idents() []string {
pub struct Checker { pub struct Checker {
pref &pref.Preferences // Preferences shared from V struct pref &pref.Preferences // Preferences shared from V struct
pub mut: pub mut:
table &ast.Table table &ast.Table
file &ast.File = 0 file &ast.File = 0
nr_errors int nr_errors int
nr_warnings int nr_warnings int
nr_notices int nr_notices int
errors []errors.Error errors []errors.Error
warnings []errors.Warning warnings []errors.Warning
notices []errors.Notice notices []errors.Notice
error_lines []int // to avoid printing multiple errors for the same line error_lines []int // to avoid printing multiple errors for the same line
expected_type ast.Type expected_type ast.Type
expected_or_type ast.Type // fn() or { 'this type' } eg. string. expected or block type expected_or_type ast.Type // fn() or { 'this type' } eg. string. expected or block type
mod string // current module name expected_expr_type ast.Type // if/match is_expr: expected_type
const_decl string mod string // current module name
const_deps []string const_decl string
const_names []string const_deps []string
global_names []string const_names []string
locked_names []string // vars that are currently locked global_names []string
rlocked_names []string // vars that are currently read-locked locked_names []string // vars that are currently locked
in_for_count int // if checker is currently in a for loop rlocked_names []string // vars that are currently read-locked
in_for_count int // if checker is currently in a for loop
// checked_ident string // to avoid infinite checker loops // checked_ident string // to avoid infinite checker loops
should_abort bool // when too many errors/warnings/notices are accumulated, .should_abort becomes true. It is checked in statement/expression loops, so the checker can return early, instead of wasting time. should_abort bool // when too many errors/warnings/notices are accumulated, .should_abort becomes true. It is checked in statement/expression loops, so the checker can return early, instead of wasting time.
returns bool returns bool
@ -3835,7 +3836,11 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
// with this value. // with this value.
pub fn (mut c Checker) enum_val(mut node ast.EnumVal) ast.Type { pub fn (mut c Checker) enum_val(mut node ast.EnumVal) ast.Type {
mut typ_idx := if node.enum_name == '' { mut typ_idx := if node.enum_name == '' {
c.expected_type.idx() if c.expected_type == ast.void_type && c.expected_expr_type != ast.void_type {
c.expected_expr_type.idx()
} else {
c.expected_type.idx()
}
} else { } else {
c.table.find_type_idx(node.enum_name) c.table.find_type_idx(node.enum_name)
} }

View File

@ -13,6 +13,12 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
c.error('unnecessary `()` in `match` condition, use `match expr {` instead of `match (expr) {`.', c.error('unnecessary `()` in `match` condition, use `match expr {` instead of `match (expr) {`.',
node.cond.pos) node.cond.pos)
} }
if node.is_expr {
c.expected_expr_type = c.expected_type
defer {
c.expected_expr_type = ast.void_type
}
}
cond_type := c.expr(node.cond) cond_type := c.expr(node.cond)
// we setting this here rather than at the end of the method // we setting this here rather than at the end of the method
// since it is used in c.match_exprs() it saves checking twice // since it is used in c.match_exprs() it saves checking twice

View File

@ -0,0 +1,24 @@
enum Foo {
a
b
c
}
fn get() Foo {
return .a
}
fn foo(f Foo) string {
println(f)
return '$f'
}
fn test_match_expr_with_enum() {
ret := foo(match get() {
.a { .b }
.b { .c }
.c { .a }
})
println(ret)
assert ret == 'b'
}