emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 1dcb737405a 1/2: Don't rewrite (nconc X nil) -> X for any X (bug#


From: Mattias Engdegård
Subject: master 1dcb737405a 1/2: Don't rewrite (nconc X nil) -> X for any X (bug#63103)
Date: Thu, 27 Apr 2023 08:21:10 -0400 (EDT)

branch: master
commit 1dcb737405a7a299fe6d01a5d9bd0c79328920b7
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>

    Don't rewrite (nconc X nil) -> X for any X (bug#63103)
    
    Since the last cdr of a non-terminal argument to `nconc` is
    overwritten no matter its value:
    
      (nconc (cons 1 2) nil) => (1)
    
    a terminating nil arg cannot just be eliminated unconditionally.
    
    * lisp/emacs-lisp/byte-opt.el (byte-optimize-nconc):
    Only eliminate a terminal nil arg to `nconc` if preceded by
    a nonempty proper list.  Right now we only bother to prove this
    for `(list ...)`, so that
    
      (nconc (list 1 2 3) nil) -> (list 1 2 3)
    
    * test/lisp/emacs-lisp/bytecomp-tests.el
    (bytecomp-tests--test-cases): Add test cases.
---
 lisp/emacs-lisp/byte-opt.el            | 11 ++++++++++-
 test/lisp/emacs-lisp/bytecomp-tests.el | 10 ++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index da997212eef..0f7a3cb2665 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1531,7 +1531,16 @@ See Info node `(elisp) Integer Basics'."
                    (prev (car newargs)))
                (cond
                 ;; Elide null args.
-                ((null arg) (loop (cdr args) newargs))
+                ((and (null arg)
+                      ;; Don't elide a terminal nil unless preceded by
+                      ;; a nonempty proper list, since that will have
+                      ;; its last cdr forced to nil.
+                      (or (cdr args)
+                          ;; FIXME: prove the 'nonempty proper list' property
+                          ;; for more forms than just `list', such as
+                          ;; `append', `mapcar' etc.
+                          (eq 'list (car-safe (car newargs)))))
+                 (loop (cdr args) newargs))
                 ;; Merge consecutive `list' args.
                 ((and (eq (car-safe arg) 'list)
                       (eq (car-safe prev) 'list))
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index 9ade47331df..222065c2e4e 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -766,6 +766,16 @@ inner loops respectively."
                         ((eq x 2) (setq y 'c)))
                   (list x y)))))
       (mapcar fn (bytecomp-test-identity '(0 1 2 3 10 11))))
+
+    ;; `nconc' nil arg elimination
+    (nconc (list 1 2 3 4) nil)
+    (nconc (list 1 2 3 4) nil nil)
+    (let ((x (cons 1 (cons 2 (cons 3 4)))))
+      (nconc x nil))
+    (let ((x (cons 1 (cons 2 (cons 3 4)))))
+      (nconc x nil nil))
+    (let ((x (cons 1 (cons 2 (cons 3 4)))))
+      (nconc nil x nil (list 5 6) nil))
     )
   "List of expressions for cross-testing interpreted and compiled code.")
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]