diff options
| author | Mattias EngdegÄrd | 2021-09-23 12:43:41 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2021-09-25 20:25:01 +0200 |
| commit | ed02b88bbae18caad650d76876940ffb58cab554 (patch) | |
| tree | 36512b017e92a76a37c63606821274bd35366924 /src/eval.c | |
| parent | 80fddff5d64ff915651eb751685b7430de00c536 (diff) | |
| download | emacs-ed02b88bbae18caad650d76876940ffb58cab554.tar.gz emacs-ed02b88bbae18caad650d76876940ffb58cab554.zip | |
Renege on anonymous &rest (bug#50268, bug#50720)
Allowing &rest without a variable name following turned out not to be
very useful, and it never worked properly. Disallow it.
* lisp/emacs-lisp/bytecomp.el (byte-compile-check-lambda-list):
* src/eval.c (funcall_lambda):
Signal error for &rest without variable name.
* doc/lispref/functions.texi (Argument List): Adjust manual.
* etc/NEWS (file): Announce.
* test/src/eval-tests.el (eval-tests--bugs-24912-and-24913):
Extend test, also checking with and without lexical binding.
(eval-tests-accept-empty-optional-rest): Reduce to...
(eval-tests-accept-empty-optional): ...this, again checking
with and without lexical binding.
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/src/eval.c b/src/eval.c index 2bb7cfe6002..66d34808f82 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -3245,6 +3245,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | |||
| 3245 | emacs_abort (); | 3245 | emacs_abort (); |
| 3246 | 3246 | ||
| 3247 | i = optional = rest = 0; | 3247 | i = optional = rest = 0; |
| 3248 | bool previous_rest = false; | ||
| 3248 | for (; CONSP (syms_left); syms_left = XCDR (syms_left)) | 3249 | for (; CONSP (syms_left); syms_left = XCDR (syms_left)) |
| 3249 | { | 3250 | { |
| 3250 | maybe_quit (); | 3251 | maybe_quit (); |
| @@ -3255,13 +3256,14 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | |||
| 3255 | 3256 | ||
| 3256 | if (EQ (next, Qand_rest)) | 3257 | if (EQ (next, Qand_rest)) |
| 3257 | { | 3258 | { |
| 3258 | if (rest) | 3259 | if (rest || previous_rest) |
| 3259 | xsignal1 (Qinvalid_function, fun); | 3260 | xsignal1 (Qinvalid_function, fun); |
| 3260 | rest = 1; | 3261 | rest = 1; |
| 3262 | previous_rest = true; | ||
| 3261 | } | 3263 | } |
| 3262 | else if (EQ (next, Qand_optional)) | 3264 | else if (EQ (next, Qand_optional)) |
| 3263 | { | 3265 | { |
| 3264 | if (optional || rest) | 3266 | if (optional || rest || previous_rest) |
| 3265 | xsignal1 (Qinvalid_function, fun); | 3267 | xsignal1 (Qinvalid_function, fun); |
| 3266 | optional = 1; | 3268 | optional = 1; |
| 3267 | } | 3269 | } |
| @@ -3287,10 +3289,11 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | |||
| 3287 | else | 3289 | else |
| 3288 | /* Dynamically bind NEXT. */ | 3290 | /* Dynamically bind NEXT. */ |
| 3289 | specbind (next, arg); | 3291 | specbind (next, arg); |
| 3292 | previous_rest = false; | ||
| 3290 | } | 3293 | } |
| 3291 | } | 3294 | } |
| 3292 | 3295 | ||
| 3293 | if (!NILP (syms_left)) | 3296 | if (!NILP (syms_left) || previous_rest) |
| 3294 | xsignal1 (Qinvalid_function, fun); | 3297 | xsignal1 (Qinvalid_function, fun); |
| 3295 | else if (i < nargs) | 3298 | else if (i < nargs) |
| 3296 | xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (nargs)); | 3299 | xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (nargs)); |