From 792fb1dc6d1435d70faff9ac7e7e27367400b20e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 21 Aug 2017 16:20:47 -0400 Subject: [PATCH] fix over-eager removal of `newvar` nodes in the presence of `isdefined` --- src/julia-syntax.scm | 23 ++++++++++++++++++----- test/core.jl | 9 +++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 42cbb9fecf7d7..02af416bba517 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3768,12 +3768,23 @@ f(x) = yt(x) '() arg-map)) body)))) -;; find newvar nodes that are unnecessary because (1) the variable is not +(define (for-each-isdefined f e) + (cond ((or (atom? e) (quoted? e)) #f) + ((and (pair? e) (eq? (car e) 'isdefined)) + (f (cadr e))) + (else + (for-each (lambda (x) (for-each-isdefined f x)) + (cdr e))))) + +;; 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. +;; 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. +;; The one exception to that is `@isdefined`, which can observe an undefined +;; variable without throwing an error. (define (definitely-initialized-vars stmts vi) (let ((vars (table)) (di (table))) @@ -3782,6 +3793,8 @@ f(x) = yt(x) di (begin (let ((e (car stmts))) + (for-each-isdefined (lambda (x) (if (has? vars x) (del! vars x))) + e) (cond ((and (pair? e) (eq? (car e) 'newvar)) (let ((vinf (var-info-for (cadr e) vi))) (if (and vinf (not (vinfo:capt vinf))) diff --git a/test/core.jl b/test/core.jl index 7c53987223365..80381bc93c824 100644 --- a/test/core.jl +++ b/test/core.jl @@ -5117,6 +5117,15 @@ f_isdefined_va(::T...) where {T} = @isdefined T @test !f_isdefined_va() @test f_isdefined_va(1, 2, 3) +# @isdefined in a loop +let a = [] + for i = 1:2 + push!(a, @isdefined(j)) + local j = 1 + end + @test a == [false, false] +end + mutable struct MyStruct22929 x::MyStruct22929 MyStruct22929() = new()