Here's another test case, not so dependent on the FILL transform:
(defun bar (x)
(let ((y (let ((z (cons nil nil)))
(let ((i 0)) (tagbody
b1 (when (= x i) (go b2)) (incf i) (go b1) b2))
z))
(w (cons t t)))
(declare (dynamic-extent y w))
(eq y w)))
Due to the bug (BAR 0) => NIL, but (BAR 1) => T.
The actual problem is in src/compiler/stack.lisp, BACK-PROPAGATE-ONE-DX-LVAR, where it tries to prevent falling into an infinite loop by refusing to traverse a block twice, which is wrong. Mea culpa. The correct thing to do is to refuse to repeat a transition between two blocks. That way, it can still visit a block multiple times, but because it can't take the same path twice it will still terminate.
Thanks to stassats for narrowing this down to a stack-analysis issue.
Here's another test case, not so dependent on the FILL transform:
(defun bar (x)
(tagbody
(when (= x i) (go b2))
(incf i)
(go b1)
b2))
(let ((y (let ((z (cons nil nil)))
(let ((i 0))
b1
z))
(w (cons t t)))
(declare (dynamic-extent y w))
(eq y w)))
Due to the bug (BAR 0) => NIL, but (BAR 1) => T.
The actual problem is in src/compiler/ stack.lisp, BACK-PROPAGATE- ONE-DX- LVAR, where it tries to prevent falling into an infinite loop by refusing to traverse a block twice, which is wrong. Mea culpa. The correct thing to do is to refuse to repeat a transition between two blocks. That way, it can still visit a block multiple times, but because it can't take the same path twice it will still terminate.
Thanks to stassats for narrowing this down to a stack-analysis issue.