Skip to content

Commit 84c3fd7

Browse files
mlechuKristofferC
authored andcommitted
lowering: Don't mutate lambda in linearize (#57416)
Fixes #56904. The associated PR (#55876) compiles a finally block, then compiles a renumbered version of it. This works if `compile` doesn't mutate its input, but in reality, lambda bodies were being `set!` when linearized. The "invalid syntax" error was a result of attempting to linearize a lambda twice. (cherry picked from commit 414aca2)
1 parent 9579515 commit 84c3fd7

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

src/julia-syntax.scm

+4-5
Original file line numberDiff line numberDiff line change
@@ -4322,11 +4322,10 @@ f(x) = yt(x)
43224322
(define (linearize e)
43234323
(cond ((or (not (pair? e)) (quoted? e)) e)
43244324
((eq? (car e) 'lambda)
4325-
(set-car! (cdddr e) (compile-body (cadddr e) (append (car (caddr e))
4326-
(cadr (caddr e)))
4327-
e)))
4328-
(else (for-each linearize (cdr e))))
4329-
e)
4325+
(list-set e 3 (compile-body (cadddr e)
4326+
(append (car (caddr e))
4327+
(cadr (caddr e))) e)))
4328+
(else (cons (car e) (map linearize (cdr e))))))
43304329

43314330
(define (valid-ir-argument? e)
43324331
(or (simple-atom? e)

src/utils.scm

+13
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,16 @@
119119
(cons (car lst) (filter (lambda (x) (not (pred x))) (cdr lst))))
120120
(else
121121
(cons (car lst) (keep-first pred (cdr lst))))))
122+
123+
(define (take lst n)
124+
(let loop ((lst lst) (n n) (out '()))
125+
(if (= n 0) (reverse out)
126+
(loop (cdr lst) (- n 1) (cons (car lst) out)))))
127+
128+
(define (drop lst n)
129+
(if (= n 0) lst
130+
(drop (cdr lst) (- n 1))))
131+
132+
;; functional update at position i
133+
(define (list-set lst i val)
134+
(append (take lst i) (list val) (drop lst (+ i 1))))

test/syntax.jl

+4
Original file line numberDiff line numberDiff line change
@@ -4103,3 +4103,7 @@ module Ambig57404
41034103
using .B
41044104
end
41054105
@test Ambig57404.S == 1
4106+
4107+
# Issue #56904 - lambda linearized twice
4108+
@test (let; try 3; finally try 1; f(() -> x); catch x; end; end; x = 7; end) === 7
4109+
@test (let; try 3; finally try 4; finally try 1; f(() -> x); catch x; end; end; end; x = 7; end) === 7

0 commit comments

Comments
 (0)