Skip to content

Commit

Permalink
fix error for global declarations shadowing locals (#35536)
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson authored Apr 22, 2020
1 parent ac82513 commit b133e92
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
27 changes: 16 additions & 11 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -2503,13 +2503,20 @@
(define (scope:implicit-globals s) (aref s 9))
(define (scope:warn-vars s) (aref s 10))

(define (var-kind var scope)
(define (var-kind var scope (exclude-top-level-globals #f))
(if scope
(or (and (memq var (scope:args scope)) 'argument)
(and (memq var (scope:locals scope)) 'local)
(and (memq var (scope:globals scope)) 'global)
(and (memq var (scope:globals scope))
(if (and exclude-top-level-globals
(null? (lam:vars (scope:lam scope)))
;; don't inherit global decls from the outermost scope block
;; in a top-level expression.
(or (not (scope:prev scope))
(not (scope:prev (scope:prev scope)))))
'none 'global))
(and (memq var (scope:sp scope)) 'static-parameter)
(var-kind var (scope:prev scope)))
(var-kind var (scope:prev scope) exclude-top-level-globals))
'none))

(define (in-scope? var scope) (not (eq? (var-kind var scope) 'none)))
Expand Down Expand Up @@ -2611,7 +2618,7 @@
(filter (if toplevel?
;; make only assigned gensyms implicitly local at top level
some-gensym?
(lambda (v) (and (memq (var-kind v scope) '(none static-parameter))
(lambda (v) (and (memq (var-kind v scope #t) '(none static-parameter))
(not (and soft?
(or (memq v (scope:implicit-globals scope))
(defined-julia-global v))))
Expand Down Expand Up @@ -2645,7 +2652,9 @@

(for-each (lambda (v)
(if (or (memq v locals-def) (memq v local-decls))
(error (string "variable \"" v "\" declared both local and global"))))
(error (string "variable \"" v "\" declared both local and global")))
(if (and (null? argnames) (memq (var-kind v scope) '(argument local)))
(error (string "`global " v "`: " v " is a local variable in its enclosing scope"))))
globals)
(if (and (pair? argnames) (eq? e (lam:body lam)))
(for-each (lambda (v)
Expand All @@ -2667,8 +2676,7 @@
(make-scope lam
'()
(append locals-nondef locals-def)
;; global declarations at the top level are not inherited
(if toplevel? '() globals)
globals
'()
(append (map cons need-rename renamed)
(map cons need-rename-def renamed-def))
Expand Down Expand Up @@ -4044,10 +4052,7 @@ f(x) = yt(x)
#f))
((global) ; keep global declarations as statements
(if value (error "misplaced \"global\" declaration"))
(let ((vname (cadr e)))
(if (var-info-for vname vi) ;; issue #7264
(error (string "`global " vname "`: " vname " is a local variable in its enclosing scope"))
(emit e))))
(emit e))
((local-def) #f)
((local) #f)
((moved-local)
Expand Down
20 changes: 20 additions & 0 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2249,3 +2249,23 @@ macro a35391(b)
:(GC.@preserve ($(esc(b)),) )
end
@test @a35391(0) === (0,)

# global declarations from the top level are not inherited by functions.
# don't allow such a declaration to override an outer local, since it's not
# clear what it should do.
@test Meta.lower(Main, :(let
x = 1
let
global x
end
end)) == Expr(:error, "`global x`: x is a local variable in its enclosing scope")
# note: this `begin` block must be at the top level
_temp_33553 = begin
global _x_this_remains_undefined
let
local _x_this_remains_undefined = 2
_x_this_remains_undefined
end
end
@test _temp_33553 == 2
@test !@isdefined(_x_this_remains_undefined)

0 comments on commit b133e92

Please sign in to comment.