with a 'lexical-binding' cookie is always heeded. To revert to the
old behavior, set 'permanently-enabled-local-variables' to nil.
++++
+** '&rest' in argument lists must always be followed by a variable name.
+Omitting the variable name after '&rest' was previously tolerated in
+some cases but not consistently so; it could lead to crashes or
+outright wrong results. Since the utility was marginal at best, it is
+now an error to omit the variable.
+
---
** 'kill-all-local-variables' has changed how it handles non-symbol hooks.
The function is documented to eliminate all buffer-local bindings
emacs_abort ();
i = optional = rest = 0;
+ bool previous_rest = false;
for (; CONSP (syms_left); syms_left = XCDR (syms_left))
{
maybe_quit ();
if (EQ (next, Qand_rest))
{
- if (rest)
+ if (rest || previous_rest)
xsignal1 (Qinvalid_function, fun);
rest = 1;
+ previous_rest = true;
}
else if (EQ (next, Qand_optional))
{
- if (optional || rest)
+ if (optional || rest || previous_rest)
xsignal1 (Qinvalid_function, fun);
optional = 1;
}
else
/* Dynamically bind NEXT. */
specbind (next, arg);
+ previous_rest = false;
}
}
- if (!NILP (syms_left))
+ if (!NILP (syms_left) || previous_rest)
xsignal1 (Qinvalid_function, fun);
else if (i < nargs)
xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (nargs));
(ert-deftest eval-tests--bugs-24912-and-24913 ()
"Check that Emacs doesn't accept weird argument lists.
Bug#24912 and Bug#24913."
- (dolist (args '((&rest &optional)
- (&rest a &optional) (&rest &optional a)
- (&optional &optional) (&optional &optional a)
- (&optional a &optional b)
- (&rest &rest) (&rest &rest a)
- (&rest a &rest b)))
- (should-error (eval `(funcall (lambda ,args)) t) :type 'invalid-function)
- (should-error (byte-compile-check-lambda-list args))
- (let ((byte-compile-debug t))
- (ert-info ((format "bytecomp: args = %S" args))
- (should-error (eval `(byte-compile (lambda ,args)) t))))))
-
-(ert-deftest eval-tests-accept-empty-optional-rest ()
- "Check that Emacs accepts empty &optional and &rest arglists.
+ (dolist (lb '(t false))
+ (ert-info ((prin1-to-string lb) :prefix "lexical-binding: ")
+ (let ((lexical-binding lb))
+ (dolist (args '((&rest &optional)
+ (&rest a &optional) (&rest &optional a)
+ (&optional &optional) (&optional &optional a)
+ (&optional a &optional b)
+ (&rest &rest) (&rest &rest a)
+ (&rest a &rest b)
+ (&rest) (&optional &rest)
+ ))
+ (ert-info ((prin1-to-string args) :prefix "args: ")
+ (should-error
+ (eval `(funcall (lambda ,args)) lb) :type 'invalid-function)
+ (should-error (byte-compile-check-lambda-list args))
+ (let ((byte-compile-debug t))
+ (should-error (eval `(byte-compile (lambda ,args)) lb)))))))))
+
+(ert-deftest eval-tests-accept-empty-optional ()
+ "Check that Emacs accepts empty &optional arglists.
Bug#24912."
- (dolist (args '((&optional) (&rest) (&optional &rest)
- (&optional &rest a) (&optional a &rest)))
- (let ((fun `(lambda ,args 'ok)))
- (ert-info ("eval")
- (should (eq (funcall (eval fun t)) 'ok)))
- (ert-info ("byte comp check")
- (byte-compile-check-lambda-list args))
- (ert-info ("bytecomp")
- (let ((byte-compile-debug t))
- (should (eq (funcall (byte-compile fun)) 'ok)))))))
+ (dolist (lb '(t false))
+ (ert-info ((prin1-to-string lb) :prefix "lexical-binding: ")
+ (let ((lexical-binding lb))
+ (dolist (args '((&optional) (&optional &rest a)))
+ (ert-info ((prin1-to-string args) :prefix "args: ")
+ (let ((fun `(lambda ,args 'ok)))
+ (ert-info ("eval")
+ (should (eq (funcall (eval fun lb)) 'ok)))
+ (ert-info ("byte comp check")
+ (byte-compile-check-lambda-list args))
+ (ert-info ("bytecomp")
+ (let ((byte-compile-debug t))
+ (should (eq (funcall (byte-compile fun)) 'ok)))))))))))
(dolist (form '(let let*))