diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4d033c589b..16a200db45 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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 { diff --git a/vlib/v/checker/tests/unknown_comptime_expr.out b/vlib/v/checker/tests/unknown_comptime_expr.out index d8d874ad2d..a778c309fe 100644 --- a/vlib/v/checker/tests/unknown_comptime_expr.out +++ b/vlib/v/checker/tests/unknown_comptime_expr.out @@ -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 | diff --git a/vlib/v/checker/tests/unknown_comptime_expr.vv b/vlib/v/checker/tests/unknown_comptime_expr.vv index fb92811bca..c3734aeb8b 100644 --- a/vlib/v/checker/tests/unknown_comptime_expr.vv +++ b/vlib/v/checker/tests/unknown_comptime_expr.vv @@ -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 +} +