checker: make it an error, to use ident outside of anon fn (#8232)

pull/8092/head
zakuro 2021-01-22 16:24:49 +09:00 committed by GitHub
parent a569dc17e8
commit 522d875489
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 17 deletions

View File

@ -8,12 +8,13 @@ import v.table
pub struct Scope { pub struct Scope {
pub mut: pub mut:
// mut: // mut:
objects map[string]ScopeObject objects map[string]ScopeObject
struct_fields []ScopeStructField struct_fields []ScopeStructField
parent &Scope parent &Scope
children []&Scope detached_from_parent bool
start_pos int children []&Scope
end_pos int start_pos int
end_pos int
} }
pub fn new_scope(parent &Scope, start_pos int) &Scope { pub fn new_scope(parent &Scope, start_pos int) &Scope {
@ -23,13 +24,17 @@ pub fn new_scope(parent &Scope, start_pos int) &Scope {
} }
} }
fn (s &Scope) dont_lookup_parent() bool {
return isnil(s.parent) || s.detached_from_parent
}
pub fn (s &Scope) find_with_scope(name string) ?(ScopeObject, &Scope) { pub fn (s &Scope) find_with_scope(name string) ?(ScopeObject, &Scope) {
mut sc := s mut sc := s
for { for {
if name in sc.objects { if name in sc.objects {
return sc.objects[name], sc return sc.objects[name], sc
} }
if isnil(sc.parent) { if sc.dont_lookup_parent() {
break break
} }
sc = sc.parent sc = sc.parent
@ -42,7 +47,7 @@ pub fn (s &Scope) find(name string) ?ScopeObject {
if name in sc.objects { if name in sc.objects {
return sc.objects[name] return sc.objects[name]
} }
if isnil(sc.parent) { if sc.dont_lookup_parent() {
break break
} }
} }
@ -56,7 +61,7 @@ pub fn (s &Scope) find_struct_field(struct_type table.Type, field_name string) ?
return field return field
} }
} }
if isnil(sc.parent) { if sc.dont_lookup_parent() {
break break
} }
} }
@ -141,7 +146,7 @@ pub fn (mut s Scope) register(obj ScopeObject) {
pub fn (s &Scope) outermost() &Scope { pub fn (s &Scope) outermost() &Scope {
mut sc := s mut sc := s
for !isnil(sc.parent) { for !sc.dont_lookup_parent() {
sc = sc.parent sc = sc.parent
} }
return sc return sc

View File

@ -9,9 +9,10 @@ vlib/v/checker/tests/fn_var.vv:4:5: error: cannot assign to `p`: expected `&fn (
3 | mut p := &f 3 | mut p := &f
4 | p = &[f] 4 | p = &[f]
| ^ | ^
5 | f = fn(mut a []int) {} 5 | i := 0
vlib/v/checker/tests/fn_var.vv:5:5: error: cannot assign to `f`: expected `fn (int) byte`, not `fn (mut []int)` 6 | println(i)
3 | mut p := &f vlib/v/checker/tests/fn_var.vv:7:31: error: undefined ident: `i`
4 | p = &[f] 5 | i := 0
5 | f = fn(mut a []int) {} 6 | println(i)
| ~~~~~~~~~~~~~~~~~~ 7 | f = fn(mut a []int) { println(i) }
| ^

View File

@ -2,4 +2,6 @@ mut f := fn(i int) byte {}
f = 4 f = 4
mut p := &f mut p := &f
p = &[f] p = &[f]
f = fn(mut a []int) {} i := 0
println(i)
f = fn(mut a []int) { println(i) }

View File

@ -447,6 +447,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
return ast.AnonFn{} return ast.AnonFn{}
} }
p.open_scope() p.open_scope()
p.scope.detached_from_parent = true
// TODO generics // TODO generics
args, _, is_variadic := p.fn_args() args, _, is_variadic := p.fn_args()
for arg in args { for arg in args {