move-return-stuff into deleted lambda

Bug #1661911 reported by Stas Boukarev on 2017-02-05
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
High
Unassigned

Bug Description

The bug reported by Eric Marsden reduces into

(defun foo ()
  (declare (optimize (debug 1)))
  (block nil
    (lambda () (return)))
  (labels ((l () (l))
           (%f (a &key)
             (l)
             (return-from foo a)))
    (%f (return-from foo))
    (%f 1)))

=> failed AVER: (SINGLETON-P SB-C::SUCC)

This is caused by move-return-stuff deleting and unlinking the return node, it only does so if the return block is deleted. And normally delete-block would handle that, but move-return-stuff points the callee return node to the caller lambda. Now the caller has two returns pointing to it, and delete-return can't handle being called twice on the same lambda.

Now unlink-node fails because the return is the only node in the deleted block, and the block has no successors, unlink-node can't handle that.

Why is move-return-stuff called on deleted stuff? It's coming from MAYBE-CONVERT-TO-ASSIGNMENT, which comes from IR1-OPTIMIZE-RETURN. And it's the tail self recursive L function that is being converted. Its parent caller is %F, but it's already let converted into an &optional-processor, and that optional processor is deleted. It's deleted, but none of the blocks that contain %F or the call to L are being marked as deleted.

Stas Boukarev (stassats) on 2017-02-05
description: updated
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers