checker: fix unresolved variables error on assignments

pull/5009/head
yuyi 2020-05-25 01:33:53 +08:00 committed by GitHub
parent 1754ba19d8
commit 641fe5c864
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 53 additions and 10 deletions

View File

@ -31,7 +31,6 @@ pub mut:
pref &pref.Preferences // Preferences shared from V struct pref &pref.Preferences // Preferences shared from V struct
in_for_count int // if checker is currently in an for loop in_for_count int // if checker is currently in an for loop
// checked_ident string // to avoid infinit checker loops // checked_ident string // to avoid infinit checker loops
var_decl_name string
returns bool returns bool
scope_returns bool scope_returns bool
mod string // current module name mod string // current module name
@ -1258,9 +1257,6 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
if is_decl && ident.name != '_' { if is_decl && ident.name != '_' {
c.check_valid_snake_case(ident.name, 'variable name', ident.pos) c.check_valid_snake_case(ident.name, 'variable name', ident.pos)
} }
if assign_stmt.op == .decl_assign {
c.var_decl_name = ident.name
}
mut ident_var_info := ident.var_info() mut ident_var_info := ident.var_info()
// c.assigned_var_name = ident.name // c.assigned_var_name = ident.name
if assign_stmt.op == .assign { if assign_stmt.op == .assign {
@ -1282,7 +1278,6 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
c.check_expr_opt_call(assign_stmt.right[i], assign_stmt.right_types[i], true) c.check_expr_opt_call(assign_stmt.right[i], assign_stmt.right_types[i], true)
} }
} }
c.var_decl_name = ''
c.expected_type = table.void_type c.expected_type = table.void_type
// c.assigned_var_name = '' // c.assigned_var_name = ''
} }
@ -1823,11 +1818,6 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
} }
pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type { pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
if ident.name == c.var_decl_name { // c.checked_ident {
// Do not allow `x := x`
c.error('unresolved: `$ident.name`', ident.pos)
return table.void_type
}
// TODO: move this // TODO: move this
if c.const_deps.len > 0 { if c.const_deps.len > 0 {
mut name := ident.name mut name := ident.name

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/assign_expr_unresolved_variables_err_a.v:2:7: error: unresolved variables `a`
1 | fn main() {
2 | a := a
| ^
3 | println(a)
4 | }

View File

@ -0,0 +1,4 @@
fn main() {
a := a
println(a)
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/assign_expr_unresolved_variables_err_b.v:2:10: error: unresolved variables `a`
1 | fn main() {
2 | a, b := a, b
| ^
3 | println('$a, $b')
4 | }

View File

@ -0,0 +1,4 @@
fn main() {
a, b := a, b
println('$a, $b')
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/assign_expr_unresolved_variables_err_c.v:2:10: error: unresolved variables `a`
1 | fn main() {
2 | a, b := a + 1, b * 3
| ^
3 | println('$a, $b')
4 | }

View File

@ -0,0 +1,4 @@
fn main() {
a, b := a + 1, b * 3
println('$a, $b')
}

View File

@ -9,6 +9,23 @@ fn (mut p Parser) assign_stmt() ast.Stmt {
return p.partial_assign_stmt([]) return p.partial_assign_stmt([])
} }
fn (mut p Parser) check_unresolved_variables(idents []ast.Ident, expr ast.Expr) {
match expr {
ast.Ident {
for ident in idents {
if ident.name == it.name {
p.error_with_pos('unresolved variables `$it.name`', it.pos)
}
}
}
ast.InfixExpr {
p.check_unresolved_variables(idents, it.left)
p.check_unresolved_variables(idents, it.right)
}
else {}
}
}
fn (mut p Parser) partial_assign_stmt(known_lhs []ast.Ident) ast.Stmt { fn (mut p Parser) partial_assign_stmt(known_lhs []ast.Ident) ast.Stmt {
mut idents := known_lhs mut idents := known_lhs
mut op := p.tok.kind mut op := p.tok.kind
@ -24,6 +41,12 @@ fn (mut p Parser) partial_assign_stmt(known_lhs []ast.Ident) ast.Stmt {
pos := p.tok.position() pos := p.tok.position()
exprs := p.parse_assign_rhs() exprs := p.parse_assign_rhs()
is_decl := op == .decl_assign is_decl := op == .decl_assign
if is_decl {
// a, b := a + 1, b
for expr in exprs {
p.check_unresolved_variables(idents, expr)
}
}
for i, ident in idents { for i, ident in idents {
known_var := p.scope.known_var(ident.name) known_var := p.scope.known_var(ident.name)
if !is_decl && !known_var { if !is_decl && !known_var {