From fdc0151a51e833c82c68cb4bb3a0de1a8d5c96a8 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 29 May 2015 01:22:40 -0400 Subject: [PATCH] always re-initialize variables to undefined at the top of their scope fixes #11065 --- src/julia-syntax.scm | 39 +++++++++++++++++++++++++++++++++------ test/core.jl | 12 ++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index e72ceb05dbb67..87536bf7f69f9 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3232,11 +3232,7 @@ So far only the second case can actually occur. (vinf (var-info-for vname vi))) (if (and vinf (not (and (pair? code) - (equal? (car code) `(newvar ,vname)))) - ;; TODO: remove the following expression to re-null - ;; all variables when they are allocated. see issue #1571 - (vinfo:capt vinf) - ) + (equal? (car code) `(newvar ,vname))))) (emit `(newvar ,vname)) #f))) ((newvar) @@ -3246,10 +3242,41 @@ So far only the second case can actually occur. #f)) (else (emit (goto-form e)))))) (compile e '()) - (cons 'body (reverse! code)))) + (let* ((stmts (reverse! code)) + (di (definitely-initialized-vars stmts vi))) + (cons 'body (filter (lambda (e) + (not (and (pair? e) (eq? (car e) 'newvar) + (has? di (cadr e))))) + stmts))))) (define to-goto-form goto-form) +;; find newvar nodes that are unnecessary because (1) the variable is not +;; captured, and (2) the variable is assigned before any branches. +;; this is used to remove newvar nodes that are not needed for re-initializing +;; variables to undefined (see issue #11065). it doesn't look for variable +;; *uses*, because any variables used-before-def that also pass this test +;; are *always* used undefined, and therefore don't need to be *re*-initialized. +(define (definitely-initialized-vars stmts vi) + (let ((vars (table)) + (di (table))) + (let loop ((stmts stmts)) + (if (null? stmts) + di + (begin + (let ((e (car stmts))) + (cond ((and (pair? e) (eq? (car e) 'newvar)) + (let ((vinf (var-info-for (cadr e) vi))) + (if (not (vinfo:capt vinf)) + (put! vars (cadr e) #t)))) + ((and (pair? e) (eq? (car e) '=)) + (if (has? vars (cadr e)) + (begin (del! vars (cadr e)) + (put! di (cadr e) #t)))) + ((and (pair? e) (memq (car e) '(goto gotoifnot))) + (set! vars (table))))) + (loop (cdr stmts))))))) + ;; macro expander (define (splice-expr? e) diff --git a/test/core.jl b/test/core.jl index 1681477163c39..f2f8f15dcf0a4 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2913,3 +2913,15 @@ end # issue #11366 f11366{T}(x::Type{Ref{T}}) = Ref{x} @test !isleaftype(Base.return_types(f11366, (Any,))[1]) + +# issue #11065, #1571 +function f11065() + for i = 1:2 + if i == 1 + z = "z is defined" + elseif i == 2 + print(z) + end + end +end +@test_throws UndefVarError f11065()