XEPs, let conversion, and inlining

Bug #1523149 reported by Stas Boukarev
14
This bug affects 2 people
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
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.

Tags: compiler
Revision history for this message
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

Revision history for this message
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)

Revision history for this message
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)
summary: - substitute-let-funargs causing a failed AVER
+ XEPs, let conversion and inlining
summary: - XEPs, let conversion and inlining
+ XEPs, let conversion, and inlining
Revision history for this message
Stas Boukarev (stassats) wrote :

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

Revision history for this message
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))))))

Revision history for this message
Stas Boukarev (stassats) wrote :

These are not failing anymore, a new failing test case:
(defun foo ()
  (declare (optimize (debug 1) speed))
  (let ((z (block nil
             (labels ((f (x)
                        (return x)))
               (declare (inline f))
               (funcall (the function #'f) t)
               (funcall (the function #'f) t)))))

    (and z
         1)))

Revision history for this message
Stas Boukarev (stassats) wrote :

5cdc24d608bd7b482dfe8bf738aa6e22d146a7d8

Changed in sbcl:
status: Triaged → Fix Committed
Stas Boukarev (stassats)
Changed in sbcl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.