parser, checker: check undefined ident in if expr using generic type name (#14734)

master
yuyi 2022-06-10 16:57:26 +08:00 committed by GitHub
parent 690a8422d1
commit fcaf529228
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 9 additions and 3 deletions

View File

@ -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() { 1 | fn main() {
2 | c := u8(`D`) 2 | c := u8(`D`)
3 | if c >= A && c <= Z { 3 | if c >= A && c <= Z {

View File

@ -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.error_with_pos("deprecated map syntax, use syntax like `{'age': 20}`",
p.tok.pos()) p.tok.pos())
} else { } 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 {} // $if T is string {}
p.expecting_type = true p.expecting_type = true
} }

View File

@ -27,6 +27,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
mut prev_guard := false mut prev_guard := false
for p.tok.kind in [.key_if, .key_else] { for p.tok.kind in [.key_if, .key_else] {
p.inside_if = true 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() } start_pos := if is_comptime { p.prev_tok.pos().extend(p.tok.pos()) } else { p.tok.pos() }
if p.tok.kind == .key_else { if p.tok.kind == .key_else {
comments << p.eat_comments() comments << p.eat_comments()
@ -40,6 +43,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
// else { // else {
has_else = true has_else = true
p.inside_if = false p.inside_if = false
p.inside_comptime_if = false
end_pos := p.prev_tok.pos() end_pos := p.prev_tok.pos()
body_pos := p.tok.pos() body_pos := p.tok.pos()
p.open_scope() p.open_scope()
@ -141,6 +145,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
end_pos := p.prev_tok.pos() end_pos := p.prev_tok.pos()
body_pos := p.tok.pos() body_pos := p.tok.pos()
p.inside_if = false p.inside_if = false
p.inside_comptime_if = false
p.open_scope() p.open_scope()
stmts := p.parse_block_no_scope(false) stmts := p.parse_block_no_scope(false)
branches << ast.IfBranch{ branches << ast.IfBranch{

View File

@ -35,6 +35,7 @@ mut:
inside_vlib_file bool // true for all vlib/ files inside_vlib_file bool // true for all vlib/ files
inside_test_file bool // when inside _test.v or _test.vv file inside_test_file bool // when inside _test.v or _test.vv file
inside_if bool inside_if bool
inside_comptime_if bool
inside_if_expr bool inside_if_expr bool
inside_if_cond bool inside_if_cond bool
inside_ct_if_expr 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 { && (!p.inside_for || p.inside_select) && !known_var {
return p.struct_init(p.mod + '.' + p.tok.lit, false) // short_syntax: false return p.struct_init(p.mod + '.' + p.tok.lit, false) // short_syntax: false
} else if p.peek_tok.kind == .lcbr } 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)) { || (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{} {...} }` // `if a == Foo{} {...}` or `match foo { Foo{} {...} }`
return p.struct_init(p.mod + '.' + p.tok.lit, false) return p.struct_init(p.mod + '.' + p.tok.lit, false)