Skip to content

Commit c61aa27

Browse files
authored
fix #23996, bug in local function capturing in lambda-optimize-vars (#24004)
1 parent 11d9783 commit c61aa27

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

src/julia-syntax.scm

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,14 +3059,29 @@ f(x) = yt(x)
30593059
(take body)
30603060
(reverse! acc)))
30613061

3062+
;; find all methods for the same function as `ex` in `body`
3063+
(define (all-methods-for ex body)
3064+
(let ((mname (method-expr-name ex)))
3065+
(expr-find-all (lambda (s)
3066+
(and (length> s 2) (eq? (car s) 'method)
3067+
(eq? (method-expr-name s) mname)))
3068+
body
3069+
identity
3070+
(lambda (x) (and (pair? x) (not (eq? (car x) 'lambda)))))))
3071+
30623072
;; clear capture bit for vars assigned once at the top, to avoid allocating
30633073
;; some unnecessary Boxes.
30643074
(define (lambda-optimize-vars! lam)
3065-
(define (expr-uses-var ex v)
3075+
(define (expr-uses-var ex v stmts)
30663076
(cond ((assignment? ex) (expr-contains-eq v (caddr ex)))
30673077
((eq? (car ex) 'method)
30683078
(and (length> ex 2)
3069-
(assq v (cadr (lam:vinfo (cadddr ex))))))
3079+
;; a method expression captures a variable if any methods for the
3080+
;; same function do.
3081+
(let ((all-methods (all-methods-for ex (cons 'body stmts))))
3082+
(any (lambda (ex)
3083+
(assq v (cadr (lam:vinfo (cadddr ex)))))
3084+
all-methods))))
30703085
(else (expr-contains-eq v ex))))
30713086
(assert (eq? (car lam) 'lambda))
30723087
(let ((vi (car (lam:vinfo lam))))
@@ -3092,7 +3107,7 @@ f(x) = yt(x)
30923107
;; TODO: reorder leading statements to put assignments where the RHS is
30933108
;; `simple-atom?` at the top.
30943109
(for-each (lambda (e)
3095-
(set! unused (filter (lambda (v) (not (expr-uses-var e v)))
3110+
(set! unused (filter (lambda (v) (not (expr-uses-var e v leading)))
30963111
unused))
30973112
(if (and (memq (car e) '(method =)) (memq (cadr e) unused))
30983113
(let ((v (assq (cadr e) vi)))
@@ -3273,9 +3288,8 @@ f(x) = yt(x)
32733288
(and name
32743289
(symbol (string "#" name "#" (current-julia-module-counter))))))
32753290
(alldefs (expr-find-all
3276-
(lambda (ex) (and (eq? (car ex) 'method)
3291+
(lambda (ex) (and (length> ex 2) (eq? (car ex) 'method)
32773292
(not (eq? ex e))
3278-
(length> ex 2)
32793293
(eq? (method-expr-name ex) name)))
32803294
(lam:body lam)
32813295
identity

test/core.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,20 @@ c23558(n,k) =
335335
end
336336
@test c23558(10, 5) == 252
337337

338+
# issue #23996
339+
function foo23996(xs...)
340+
rets = []
341+
bar(::Int) = push!(rets, 1)
342+
foobar() = push!(rets, 3)
343+
bar(::AbstractFloat) = push!(rets, 2)
344+
bar(::Bool) = foobar()
345+
for x in xs
346+
bar(x)
347+
end
348+
rets
349+
end
350+
@test foo23996(1,2.0,false) == [1,2,3]
351+
338352
# variable scope, globals
339353
glob_x = 23
340354
function glotest()

0 commit comments

Comments
 (0)