diff --git a/vlib/v/ast/scope.v b/vlib/v/ast/scope.v index fa304e07fc..672b3b173a 100644 --- a/vlib/v/ast/scope.v +++ b/vlib/v/ast/scope.v @@ -8,12 +8,13 @@ import v.table pub struct Scope { pub mut: // mut: - objects map[string]ScopeObject - struct_fields []ScopeStructField - parent &Scope - children []&Scope - start_pos int - end_pos int + objects map[string]ScopeObject + struct_fields []ScopeStructField + parent &Scope + detached_from_parent bool + children []&Scope + start_pos int + end_pos int } 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) { mut sc := s for { if name in sc.objects { return sc.objects[name], sc } - if isnil(sc.parent) { + if sc.dont_lookup_parent() { break } sc = sc.parent @@ -42,7 +47,7 @@ pub fn (s &Scope) find(name string) ?ScopeObject { if name in sc.objects { return sc.objects[name] } - if isnil(sc.parent) { + if sc.dont_lookup_parent() { break } } @@ -56,7 +61,7 @@ pub fn (s &Scope) find_struct_field(struct_type table.Type, field_name string) ? return field } } - if isnil(sc.parent) { + if sc.dont_lookup_parent() { break } } @@ -141,7 +146,7 @@ pub fn (mut s Scope) register(obj ScopeObject) { pub fn (s &Scope) outermost() &Scope { mut sc := s - for !isnil(sc.parent) { + for !sc.dont_lookup_parent() { sc = sc.parent } return sc diff --git a/vlib/v/checker/tests/fn_var.out b/vlib/v/checker/tests/fn_var.out index ad42c57e6b..ace817b996 100644 --- a/vlib/v/checker/tests/fn_var.out +++ b/vlib/v/checker/tests/fn_var.out @@ -9,9 +9,10 @@ vlib/v/checker/tests/fn_var.vv:4:5: error: cannot assign to `p`: expected `&fn ( 3 | mut p := &f 4 | p = &[f] | ^ - 5 | f = fn(mut a []int) {} -vlib/v/checker/tests/fn_var.vv:5:5: error: cannot assign to `f`: expected `fn (int) byte`, not `fn (mut []int)` - 3 | mut p := &f - 4 | p = &[f] - 5 | f = fn(mut a []int) {} - | ~~~~~~~~~~~~~~~~~~ + 5 | i := 0 + 6 | println(i) +vlib/v/checker/tests/fn_var.vv:7:31: error: undefined ident: `i` + 5 | i := 0 + 6 | println(i) + 7 | f = fn(mut a []int) { println(i) } + | ^ diff --git a/vlib/v/checker/tests/fn_var.vv b/vlib/v/checker/tests/fn_var.vv index a8049c34d7..c94a872672 100644 --- a/vlib/v/checker/tests/fn_var.vv +++ b/vlib/v/checker/tests/fn_var.vv @@ -2,4 +2,6 @@ mut f := fn(i int) byte {} f = 4 mut p := &f p = &[f] -f = fn(mut a []int) {} +i := 0 +println(i) +f = fn(mut a []int) { println(i) } diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 8ac35a5186..4e6407dfdc 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -447,6 +447,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn { return ast.AnonFn{} } p.open_scope() + p.scope.detached_from_parent = true // TODO generics args, _, is_variadic := p.fn_args() for arg in args {