Subject: bug#30872: incorrect byte-compile of closure called from local funcalled function

From: Noam Postavsky <[email-masked]>
Date: Thu, 07 Jun 2018 20:33:00 -0400

Okay, I think I found the problem.  In case of a lambda lifted function
we weren't doing this part of cconv--convert-function:

    (dolist (arg args)
      (if (not (member (cons (list arg) parentform) cconv-captured+mutated))
          (if (assq arg new-env) (push `(,arg) new-env))
        (push `(,arg . (car-safe ,arg)) new-env)
        (push `(,arg (list ,arg)) letbind)))

so `params' wasn't handled properly.  I copied and adapted that code to
the corresponding place in cconv-convert, and it seems to work.  Please
review for sanity.

>From dbdfb6c0b2bfa497178afcede7a8d0bbde4a00d7 Mon Sep 17 00:00:00 2001
From: Noam Postavsky <[email-masked]>
Date: Thu, 7 Jun 2018 19:58:47 -0400
Subject: [PATCH v1] Don't forget to analyse args of lambda lifted functions
 (Bug#30872)

* lisp/emacs-lisp/cconv.el (cconv-convert): Do the
(defun foo (... m-arg ...) ...) => (defun foo (... m-arg
...) (let ((m-arg (list m-arg))) ...)) transformation for mutated args
of lambda lifted functions as well.
---
 lisp/emacs-lisp/cconv.el | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index 02fe794467..e6e877846f 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -352,18 +352,25 @@ cconv-convert
                           (funargs (cadr fun))
                           (funcvars (append fvs funargs))
                           (funcbody (cddr fun))
-                          (funcbody-env ()))
+                          (funcbody-env ())
+                          (letbind ()))
                      (push `(,var . (apply-partially ,var . ,fvs)) new-env)
                      (dolist (fv fvs)
                        (cl-pushnew fv new-extend)
                        (if (and (eq 'car-safe (car-safe (cdr (assq fv env))))
                                 (not (memq fv funargs)))
                            (push `(,fv . (car-safe ,fv)) funcbody-env)))
-                     `(function (lambda ,funcvars .
-                                  ,(mapcar (lambda (form)
-                                             (cconv-convert
-                                              form funcbody-env nil))
-                                           funcbody)))))
+                     (dolist (arg funargs)
+                       (if (not (member (cons (list arg) value) cconv-captured+mutated))
+                           (if (assq arg funcbody-env) (push `(,arg) funcbody-env))
+                         (push `(,arg . (car-safe ,arg)) funcbody-env)
+                         (push `(,arg (list ,arg)) letbind)))
+                     `(function (lambda ,funcvars
+                                  (let ,letbind .
+                                       ,(mapcar (lambda (form)
+                                                  (cconv-convert
+                                                   form funcbody-env nil))
+                                                funcbody))))))
 
                   ;; Check if it needs to be turned into a "ref-cell".
                   ((member (cons binder form) cconv-captured+mutated)
-- 
2.11.0