From fcaf529228634e3230212a6aab0a81233b0fd02f Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 10 Jun 2022 16:57:26 +0800 Subject: [PATCH] parser, checker: check undefined ident in if expr using generic type name (#14734) --- .../tests/generic_type_name_in_non_generic_function.out | 2 +- vlib/v/parser/expr.v | 2 +- vlib/v/parser/if_match.v | 5 +++++ vlib/v/parser/parser.v | 3 ++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/vlib/v/checker/tests/generic_type_name_in_non_generic_function.out b/vlib/v/checker/tests/generic_type_name_in_non_generic_function.out index 7a6fcf1d0a..c4db510710 100644 --- a/vlib/v/checker/tests/generic_type_name_in_non_generic_function.out +++ b/vlib/v/checker/tests/generic_type_name_in_non_generic_function.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/generic_type_name_in_non_generic_function.vv:3:10: error: unexpected generic variable in non-generic function `main` +vlib/v/checker/tests/generic_type_name_in_non_generic_function.vv:3:10: error: undefined ident: `A` 1 | fn main() { 2 | c := u8(`D`) 3 | if c >= A && c <= Z { diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index dd6e9c9afe..3fddc0440b 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -55,7 +55,7 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr { p.error_with_pos("deprecated map syntax, use syntax like `{'age': 20}`", p.tok.pos()) } else { - if p.inside_if && p.is_generic_name() && p.peek_tok.kind != .dot { + if p.inside_comptime_if && p.is_generic_name() && p.peek_tok.kind != .dot { // $if T is string {} p.expecting_type = true } diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index 77944b0bca..28e08a5b08 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -27,6 +27,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { mut prev_guard := false for p.tok.kind in [.key_if, .key_else] { p.inside_if = true + if is_comptime { + p.inside_comptime_if = true + } start_pos := if is_comptime { p.prev_tok.pos().extend(p.tok.pos()) } else { p.tok.pos() } if p.tok.kind == .key_else { comments << p.eat_comments() @@ -40,6 +43,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { // else { has_else = true p.inside_if = false + p.inside_comptime_if = false end_pos := p.prev_tok.pos() body_pos := p.tok.pos() p.open_scope() @@ -141,6 +145,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { end_pos := p.prev_tok.pos() body_pos := p.tok.pos() p.inside_if = false + p.inside_comptime_if = false p.open_scope() stmts := p.parse_block_no_scope(false) branches << ast.IfBranch{ diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index c8777a11c9..210096d8a9 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -35,6 +35,7 @@ mut: inside_vlib_file bool // true for all vlib/ files inside_test_file bool // when inside _test.v or _test.vv file inside_if bool + inside_comptime_if bool inside_if_expr bool inside_if_cond bool inside_ct_if_expr bool @@ -2419,7 +2420,7 @@ pub fn (mut p Parser) name_expr() ast.Expr { && (!p.inside_for || p.inside_select) && !known_var { return p.struct_init(p.mod + '.' + p.tok.lit, false) // short_syntax: false } else if p.peek_tok.kind == .lcbr - && ((p.inside_if && lit0_is_capital && !known_var && language == .v) + && ((p.inside_if && lit0_is_capital && p.tok.lit.len > 1 && !known_var && language == .v) || (p.inside_match_case && p.tok.kind == .name && p.peek_tok.pos - p.tok.pos == p.tok.len)) { // `if a == Foo{} {...}` or `match foo { Foo{} {...} }` return p.struct_init(p.mod + '.' + p.tok.lit, false)