mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser: check undefined ident in if guard expr (#15253)
This commit is contained in:
parent
242ade8938
commit
17ce1a0e8d
7
vlib/v/checker/tests/undefined_ident_in_if_guard_err.out
Normal file
7
vlib/v/checker/tests/undefined_ident_in_if_guard_err.out
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
vlib/v/checker/tests/undefined_ident_in_if_guard_err.vv:6:11: error: undefined variable: `re`
|
||||||
|
4 |
|
||||||
|
5 | fn main() {
|
||||||
|
6 | if re := re.regex_opt('a') {
|
||||||
|
| ~~
|
||||||
|
7 | print('Hooray')
|
||||||
|
8 | }
|
9
vlib/v/checker/tests/undefined_ident_in_if_guard_err.vv
Normal file
9
vlib/v/checker/tests/undefined_ident_in_if_guard_err.vv
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import regex
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if re := re.regex_opt('a') {
|
||||||
|
print('Hooray')
|
||||||
|
}
|
||||||
|
}
|
@ -118,6 +118,102 @@ fn (mut p Parser) check_undefined_variables(exprs []ast.Expr, val ast.Expr) ? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut p Parser) check_undefined_variables_by_names(names []string, val ast.Expr) ? {
|
||||||
|
p.expr_level++
|
||||||
|
defer {
|
||||||
|
p.expr_level--
|
||||||
|
}
|
||||||
|
if p.expr_level > parser.max_expr_level {
|
||||||
|
return error('expr level > $parser.max_expr_level')
|
||||||
|
}
|
||||||
|
match val {
|
||||||
|
ast.Ident {
|
||||||
|
for name in names {
|
||||||
|
if name == val.name && val.kind != .blank_ident {
|
||||||
|
p.error_with_pos('undefined variable: `$val.name`', val.pos)
|
||||||
|
return error('undefined variable: `$val.name`')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.ArrayInit {
|
||||||
|
if val.has_cap {
|
||||||
|
p.check_undefined_variables_by_names(names, val.cap_expr)?
|
||||||
|
}
|
||||||
|
if val.has_len {
|
||||||
|
p.check_undefined_variables_by_names(names, val.len_expr)?
|
||||||
|
}
|
||||||
|
if val.has_default {
|
||||||
|
p.check_undefined_variables_by_names(names, val.default_expr)?
|
||||||
|
}
|
||||||
|
for expr in val.exprs {
|
||||||
|
p.check_undefined_variables_by_names(names, expr)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.CallExpr {
|
||||||
|
p.check_undefined_variables_by_names(names, val.left)?
|
||||||
|
for arg in val.args {
|
||||||
|
p.check_undefined_variables_by_names(names, arg.expr)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.InfixExpr {
|
||||||
|
p.check_undefined_variables_by_names(names, val.left)?
|
||||||
|
p.check_undefined_variables_by_names(names, val.right)?
|
||||||
|
}
|
||||||
|
ast.IfExpr {
|
||||||
|
p.check_undefined_variables_by_names(names, val.left)?
|
||||||
|
for branch in val.branches {
|
||||||
|
p.check_undefined_variables_by_names(names, branch.cond)?
|
||||||
|
for stmt in branch.stmts {
|
||||||
|
if stmt is ast.ExprStmt {
|
||||||
|
p.check_undefined_variables_by_names(names, stmt.expr)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.MapInit {
|
||||||
|
for key in val.keys {
|
||||||
|
p.check_undefined_variables_by_names(names, key)?
|
||||||
|
}
|
||||||
|
for value in val.vals {
|
||||||
|
p.check_undefined_variables_by_names(names, value)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.MatchExpr {
|
||||||
|
p.check_undefined_variables_by_names(names, val.cond)?
|
||||||
|
for branch in val.branches {
|
||||||
|
for expr in branch.exprs {
|
||||||
|
p.check_undefined_variables_by_names(names, expr)?
|
||||||
|
}
|
||||||
|
for stmt in branch.stmts {
|
||||||
|
if stmt is ast.ExprStmt {
|
||||||
|
p.check_undefined_variables_by_names(names, stmt.expr)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.ParExpr {
|
||||||
|
p.check_undefined_variables_by_names(names, val.expr)?
|
||||||
|
}
|
||||||
|
ast.PostfixExpr {
|
||||||
|
p.check_undefined_variables_by_names(names, val.expr)?
|
||||||
|
}
|
||||||
|
ast.PrefixExpr {
|
||||||
|
p.check_undefined_variables_by_names(names, val.right)?
|
||||||
|
}
|
||||||
|
ast.StringInterLiteral {
|
||||||
|
for expr_ in val.exprs {
|
||||||
|
p.check_undefined_variables_by_names(names, expr_)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.StructInit {
|
||||||
|
for field in val.fields {
|
||||||
|
p.check_undefined_variables_by_names(names, field.expr)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool {
|
fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool {
|
||||||
val_str := val.str()
|
val_str := val.str()
|
||||||
match val {
|
match val {
|
||||||
|
@ -87,6 +87,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||||||
p.open_scope()
|
p.open_scope()
|
||||||
is_guard = true
|
is_guard = true
|
||||||
mut vars := []ast.IfGuardVar{}
|
mut vars := []ast.IfGuardVar{}
|
||||||
|
mut var_names := []string{}
|
||||||
for {
|
for {
|
||||||
mut var := ast.IfGuardVar{}
|
mut var := ast.IfGuardVar{}
|
||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
@ -97,6 +98,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||||||
var.is_mut = is_mut
|
var.is_mut = is_mut
|
||||||
var.pos = p.tok.pos()
|
var.pos = p.tok.pos()
|
||||||
var.name = p.check_name()
|
var.name = p.check_name()
|
||||||
|
var_names << var.name
|
||||||
|
|
||||||
if p.scope.known_var(var.name) {
|
if p.scope.known_var(var.name) {
|
||||||
p.error_with_pos('redefinition of `$var.name`', var.pos)
|
p.error_with_pos('redefinition of `$var.name`', var.pos)
|
||||||
@ -115,7 +117,10 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||||||
p.error_with_pos('if guard condition expression is illegal, it should return optional',
|
p.error_with_pos('if guard condition expression is illegal, it should return optional',
|
||||||
expr.pos())
|
expr.pos())
|
||||||
}
|
}
|
||||||
|
p.check_undefined_variables_by_names(var_names, expr) or {
|
||||||
|
p.error_with_pos(err.msg(), pos)
|
||||||
|
break
|
||||||
|
}
|
||||||
cond = ast.IfGuardExpr{
|
cond = ast.IfGuardExpr{
|
||||||
vars: vars
|
vars: vars
|
||||||
expr: expr
|
expr: expr
|
||||||
|
Loading…
x
Reference in New Issue
Block a user