checker: check `match` with type alias (#10863)

pull/10873/head^2
Daniel Däschle 2021-07-20 14:06:36 +02:00 committed by GitHub
parent 60b705b4c4
commit f6402eae10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 6 deletions

View File

@ -6085,6 +6085,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
// parser failed, stop checking // parser failed, stop checking
return return
} }
expr_type_sym := c.table.get_type_symbol(expr_type)
if cond_type_sym.kind == .interface_ { if cond_type_sym.kind == .interface_ {
// TODO // TODO
// This generates a memory issue with TCC // This generates a memory issue with TCC
@ -6094,7 +6095,6 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
expr_pos := expr.position() expr_pos := expr.position()
if c.type_implements(expr_type, c.expected_type, expr_pos) { if c.type_implements(expr_type, c.expected_type, expr_pos) {
if !expr_type.is_ptr() && !expr_type.is_pointer() && !c.inside_unsafe { if !expr_type.is_ptr() && !expr_type.is_pointer() && !c.inside_unsafe {
expr_type_sym := c.table.get_type_symbol(expr_type)
if expr_type_sym.kind != .interface_ { if expr_type_sym.kind != .interface_ {
c.mark_as_referenced(mut &branch.exprs[k], true) c.mark_as_referenced(mut &branch.exprs[k], true)
} }
@ -6106,10 +6106,14 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
expect_str := c.table.type_to_str(node.cond_type) expect_str := c.table.type_to_str(node.cond_type)
c.error('`$expect_str` has no variant `$expr_str`', expr.position()) c.error('`$expect_str` has no variant `$expr_str`', expr.position())
} }
} else if cond_type_sym.info is ast.Alias && expr_type_sym.info is ast.Struct {
expr_str := c.table.type_to_str(expr_type)
expect_str := c.table.type_to_str(node.cond_type)
c.error('cannot match alias type `$expect_str` with `$expr_str`', expr.position())
} else if !c.check_types(expr_type, node.cond_type) { } else if !c.check_types(expr_type, node.cond_type) {
expr_str := c.table.type_to_str(expr_type) expr_str := c.table.type_to_str(expr_type)
expect_str := c.table.type_to_str(node.cond_type) expect_str := c.table.type_to_str(node.cond_type)
c.error('cannot match `$expr_str` with `$expect_str` condition', expr.position()) c.error('cannot match `$expect_str` with `$expr_str`', expr.position())
} }
branch_exprs[key] = val + 1 branch_exprs[key] = val + 1
} }

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/match_alias_type_err.vv:13:3: error: cannot match alias type `Stmt` with `SelectStmt`
11 |
12 | match stmt {
13 | SelectStmt { panic('select') }
| ~~~~~~~~~~
14 | else { /* why? */ }
15 | }

View File

@ -0,0 +1,16 @@
type Stmt = SelectStmt
struct SelectStmt {}
fn parse(sql string) Stmt {
return SelectStmt{}
}
fn main() {
stmt := parse('select 123')
match stmt {
SelectStmt { panic('select') }
else { /* why? */ }
}
}

View File

@ -1,11 +1,11 @@
vlib/v/checker/tests/match_expr_and_expected_type_error.vv:3:3: error: cannot match `string` with `rune` condition vlib/v/checker/tests/match_expr_and_expected_type_error.vv:3:3: error: cannot match `rune` with `string`
1 | ch := `a` 1 | ch := `a`
2 | match ch { 2 | match ch {
3 | 'a' {} 3 | 'a' {}
| ~~~ | ~~~
4 | else {} 4 | else {}
5 | } 5 | }
vlib/v/checker/tests/match_expr_and_expected_type_error.vv:9:3: error: cannot match `string` with `int` condition vlib/v/checker/tests/match_expr_and_expected_type_error.vv:9:3: error: cannot match `int` with `string`
7 | i := 123 7 | i := 123
8 | match i { 8 | match i {
9 | 'a' {} 9 | 'a' {}

View File

@ -5,14 +5,14 @@ vlib/v/checker/tests/match_undefined_cond.vv:4:15: error: undefined ident: `Asd`
| ~~~ | ~~~
5 | 1 { 'foo' } 5 | 1 { 'foo' }
6 | 2 { 'test' } 6 | 2 { 'test' }
vlib/v/checker/tests/match_undefined_cond.vv:5:3: error: cannot match `int literal` with `void` condition vlib/v/checker/tests/match_undefined_cond.vv:5:3: error: cannot match `void` with `int literal`
3 | fn main() { 3 | fn main() {
4 | res := match Asd { 4 | res := match Asd {
5 | 1 { 'foo' } 5 | 1 { 'foo' }
| ^ | ^
6 | 2 { 'test' } 6 | 2 { 'test' }
7 | else { '' } 7 | else { '' }
vlib/v/checker/tests/match_undefined_cond.vv:6:3: error: cannot match `int literal` with `void` condition vlib/v/checker/tests/match_undefined_cond.vv:6:3: error: cannot match `void` with `int literal`
4 | res := match Asd { 4 | res := match Asd {
5 | 1 { 'foo' } 5 | 1 { 'foo' }
6 | 2 { 'test' } 6 | 2 { 'test' }