XEPs, let conversion, and inlining

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

Bug Description

From sbcl-bugs by cage:

((lambda ()
   (declare (optimize debug))
   (block nil
     (flet ((fun (x) (unless (funcall #'null x) (return))))
       (declare (inline fun))
       (map-into (vector 1) #'fun (coerce #(1) 'vector))))))
failed AVER:
    (NOT
     (SB-C::FUNCTIONAL-HAS-EXTERNAL-REFERENCES-P SB-C::CLAMBDA))
removing substitute-let-funargs from maybe-let-convert solves it. But a modified case still fails

(declaim (inline bar))
(defun bar (f)
  (funcall f))

(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return)))
         (declare (inline fun))
         (bar #'fun))))))

with substitute-let-funargs
failed AVER: (NOT (SB-C::FUNCTIONAL-HAS-EXTERNAL-REFERENCES-P SB-C::CLAMBDA))

without:
failed AVER: (SUBSETP SB-C::END SB-C::END-STACK)

A test cases which fails the same either way:
(defun moo ())
(declaim (inline bar))
(defun bar (f)
  (multiple-value-call f (moo)))

(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return)))
         (declare (inline fun))
         (bar #'fun))))))

The value NIL is not of type SB-C::NODE.

Stas Boukarev (stassats) wrote :

It is influenced by %coerce-callable-to-fun
(declaim (inline bar))
(defun bar (f)
  (%funcall f))

(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return nil)))
         (declare (inline fun))
         (bar #'fun))))))

Doesn't fail

while
(defun bar (f)
  (%funcall (%coerce-callable-to-fun f)))
does with
    (NOT (FUNCTIONAL-HAS-EXTERNAL-REFERENCES-P CLAMBDA))

doing
(defknown x (t) t)
(deftransform x ((fun))
  'fun)

(defun bar (f)
  (%funcall (x f)))

gives failed AVER: (SUBSETP END END-STACK)

the difference is %coerce-callable-to-fun gives up once

Stas Boukarev (stassats) wrote :

BAR can go local actually
(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return nil))
              (bar (f)
                (%funcall (x f))))
         (declare (inline fun bar))
         (bar #'fun))))))

Interestingly,
(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return nil))
              (bar (f)
                (%funcall (x f))))
         (declare (inline fun bar))
         (bar #'fun))
       10))))

Fails with
failed AVER:
    (NOT (FUNCTIONAL-HAS-EXTERNAL-REFERENCES-P CLAMBDA))
not
failed AVER: (SUBSETP END END-STACK)

Stas Boukarev (stassats) wrote :

Another failure mode
(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return nil))
              (bar (f)
                (funcall f)))
         (declare (inline fun bar))
         (print #'fun)
         (bar #'fun))))))

The value
  NIL
is not of type
  SB-C::IR2-LVAR

Stas Boukarev (stassats) on 2016-09-08
summary: - substitute-let-funargs causing a failed AVER
+ XEPs, let conversion and inlining
summary: - XEPs, let conversion and inlining
+ XEPs, let conversion, and inlining
Stas Boukarev (stassats) wrote :

Smaller
(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return nil)))
         (declare (inline fun))
         (print #'fun)
         (fun))))))

Stas Boukarev (stassats) wrote :

Another variation for
    (NOT
     (SB-C::FUNCTIONAL-HAS-EXTERNAL-REFERENCES-P SB-C::CLAMBDA))

(defun foo ()
  ((lambda ()
     (declare (optimize debug))
     (block nil
       (flet ((fun () (return nil)))
         (declare (inline fun))
         #'fun
         (fun))))))

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers