checker: check left selector expression in `$if left is right` (#8987)

pull/8992/head
Nick Treleaven 2021-02-26 20:51:35 +00:00 committed by GitHub
parent 51fae95339
commit 8874379c48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 4 deletions

View File

@ -4804,12 +4804,16 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
mut comptime_field_name := ''
if branch.cond is ast.InfixExpr {
if branch.cond.op == .key_is {
left := branch.cond.left
if branch.cond.right !is ast.Type {
c.error('invalid `\$if` condition: expected a type', branch.cond.right.position())
return 0
}
got_type := c.unwrap_generic((branch.cond.right as ast.Type).typ)
sym := c.table.get_type_symbol(got_type)
if sym.kind == .placeholder || got_type.has_flag(.generic) {
c.error('unknown type `$sym.name`', branch.cond.right.position())
}
left := branch.cond.left
if left is ast.SelectorExpr {
comptime_field_name = left.expr.str()
c.comptime_fields_type[comptime_field_name] = got_type
@ -4968,11 +4972,13 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
return l && r // skip (return true) only if both should be skipped
}
.key_is, .not_is {
if (cond.left is ast.SelectorExpr || cond.left is ast.Type)
&& cond.right is ast.Type {
if cond.left is ast.SelectorExpr || cond.left is ast.Type {
// $if method.@type is string
c.expr(cond.left)
return false
} else {
c.error('invalid `\$if` condition: $cond.left', cond.pos)
c.error('invalid `\$if` condition: expected a type or selector expression',
cond.left.position())
}
}
.eq, .ne {

View File

@ -11,3 +11,32 @@ vlib/v/checker/tests/unknown_comptime_expr.vv:8:6: error: definition of `bar` is
8 | $if bar == 0 {}
| ~~~
9 | }
10 |
vlib/v/checker/tests/unknown_comptime_expr.vv:13:6: error: undefined ident: `huh`
11 | fn if_is() {
12 | s := S1{}
13 | $if huh.typ is T {}
| ~~~
14 | $if s is int {}
15 | $if s.i is 5 {}
vlib/v/checker/tests/unknown_comptime_expr.vv:14:6: error: invalid `$if` condition: expected a type or selector expression
12 | s := S1{}
13 | $if huh.typ is T {}
14 | $if s is int {}
| ^
15 | $if s.i is 5 {}
16 | $if s.i is T {}
vlib/v/checker/tests/unknown_comptime_expr.vv:15:13: error: invalid `$if` condition: expected a type
13 | $if huh.typ is T {}
14 | $if s is int {}
15 | $if s.i is 5 {}
| ^
16 | $if s.i is T {}
17 | }
vlib/v/checker/tests/unknown_comptime_expr.vv:16:13: error: unknown type `T`
14 | $if s is int {}
15 | $if s.i is 5 {}
16 | $if s.i is T {}
| ^
17 | }
18 |

View File

@ -7,3 +7,16 @@ fn main() {
bar := unknown_at_ct()
$if bar == 0 {}
}
fn if_is() {
s := S1{}
$if huh.typ is T {}
$if s is int {}
$if s.i is 5 {}
$if s.i is T {}
}
struct S1 {
i int
}