Skip to content

Commit ebfebfd

Browse files
committed
always re-initialize variables to undefined at the top of their scope
fixes #11065
1 parent 6b35206 commit ebfebfd

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

src/julia-syntax.scm

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3232,11 +3232,7 @@ So far only the second case can actually occur.
32323232
(vinf (var-info-for vname vi)))
32333233
(if (and vinf
32343234
(not (and (pair? code)
3235-
(equal? (car code) `(newvar ,vname))))
3236-
;; TODO: remove the following expression to re-null
3237-
;; all variables when they are allocated. see issue #1571
3238-
(vinfo:capt vinf)
3239-
)
3235+
(equal? (car code) `(newvar ,vname)))))
32403236
(emit `(newvar ,vname))
32413237
#f)))
32423238
((newvar)
@@ -3246,10 +3242,41 @@ So far only the second case can actually occur.
32463242
#f))
32473243
(else (emit (goto-form e))))))
32483244
(compile e '())
3249-
(cons 'body (reverse! code))))
3245+
(let* ((stmts (reverse! code))
3246+
(di (definitely-initialized-vars stmts vi)))
3247+
(cons 'body (filter (lambda (e)
3248+
(not (and (pair? e) (eq? (car e) 'newvar)
3249+
(has? di (cadr e)))))
3250+
stmts)))))
32503251

32513252
(define to-goto-form goto-form)
32523253

3254+
;; find newvar nodes that are unnecessary because (1) the variable is not
3255+
;; captured, and (2) the variable is assigned before any branches.
3256+
;; this is used to remove newvar nodes that are not needed for re-initializing
3257+
;; variables to undefined (see issue #11065). it doesn't look for variable
3258+
;; *uses*, because any variables used-before-def that also pass this test
3259+
;; are *always* used undefined, and therefore don't need to be *re*-initialized.
3260+
(define (definitely-initialized-vars stmts vi)
3261+
(let ((vars (table))
3262+
(di (table)))
3263+
(let loop ((stmts stmts))
3264+
(if (null? stmts)
3265+
di
3266+
(begin
3267+
(let ((e (car stmts)))
3268+
(cond ((and (pair? e) (eq? (car e) 'newvar))
3269+
(let ((vinf (var-info-for (cadr e) vi)))
3270+
(if (not (vinfo:capt vinf))
3271+
(put! vars (cadr e) #t))))
3272+
((and (pair? e) (eq? (car e) '=))
3273+
(if (has? vars (cadr e))
3274+
(begin (del! vars (cadr e))
3275+
(put! di (cadr e) #t))))
3276+
((and (pair? e) (memq (car e) '(goto gotoifnot)))
3277+
(set! vars (table)))))
3278+
(loop (cdr stmts)))))))
3279+
32533280
;; macro expander
32543281

32553282
(define (splice-expr? e)

test/core.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2913,3 +2913,15 @@ end
29132913
# issue #11366
29142914
f11366{T}(x::Type{Ref{T}}) = Ref{x}
29152915
@test !isleaftype(Base.return_types(f11366, (Any,))[1])
2916+
2917+
# issue #11065, #1571
2918+
function f11065()
2919+
for i = 1:2
2920+
if i == 1
2921+
z = "z is defined"
2922+
elseif i == 2
2923+
print(z)
2924+
end
2925+
end
2926+
end
2927+
@test_throws UndefVarError f11065()

0 commit comments

Comments
 (0)