Subject: Re: bug#40968: 28.0.50; (apply nil)

From: Noam Postavsky <[email-masked]>
Date: Thu, 07 May 2020 07:54:10 -0400

Mattias Engdegård <[email-masked]> writes:

> 7 maj 2020 kl. 08.53 skrev Pip Cet <[email-masked]>:
>
>> It is incomplete. However, I've yet to find an elegant way to fix the
>> byte compiler and get it to emit the right error message. Can you
>> think of one?
>
> You are right, that's a puzzle. No, I cannot think of an elegant way
> (but a few inelegant ones).

The obvious solution is just to leave the weird single arg form
unoptimized.  Otherwise, what about your earlier suggestion?

    (apply X) == (apply (car X) (cdr X))

> It's probably not worth the trouble; just change the error test case

By the way, bytecomp-check-1 already ignores differences between error
types.  So the test case doesn't need a condition-case at all if we
don't care about which particular error is signalled.

--- i/lisp/emacs-lisp/byte-opt.el
+++ w/lisp/emacs-lisp/byte-opt.el
@@ -1100,7 +1100,7 @@ byte-optimize-apply
   ;; The funcall optimizer can then transform (funcall 'foo ...) -> (foo ...).
   (if (= (length form) 2)
       ;; single-argument `apply' is special (bug#40968)
-      (byte-optimize-apply `(apply #'funcall ,(cadr form)))
+      (byte-optimize-apply `(apply (car ,(cadr form)) (cdr ,(cadr form))))
     (let ((fn (nth 1 form))
 	  (last (nth (1- (length form)) form))) ; I think this really is fastest
       (or (if (or (null last)
diff --git i/src/eval.c w/src/eval.c
index 77f54ad7b1..836be7a906 100644
--- i/src/eval.c
+++ w/src/eval.c
@@ -2373,10 +2373,11 @@ DEFUN ("apply", Fapply, Sapply, 1, MANY, 0,
   Lisp_Object fun = args[0];
   USE_SAFE_ALLOCA;
 
-  ptrdiff_t numargs = list_length (spread_arg);
+  if (nargs == 1)
+    /* Special case: FUN is really a list of (FUNCTION . ARGS).  */
+    return CALLN (Fapply, CAR (fun), CDR (fun));
 
-  if (numargs == 0 && nargs == 1)
-    wrong_type_argument (Qconsp, spread_arg);
+  ptrdiff_t numargs = list_length (spread_arg);
 
   if (numargs == 0)
     return Ffuncall (nargs - 1, args);