summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
authorMattias EngdegÄrd <mattiase@acm.org>2021-12-20 11:59:22 +0100
committerMattias EngdegÄrd <mattiase@acm.org>2021-12-20 16:26:02 +0100
commit92ffe44834b8f77ee3f4d37edfdb19f30a376869 (patch)
tree505872b790d2b6799d4b26a34187ca834d3a4475 /lisp/emacs-lisp
parent8706f6fde13729bf330693cfd163773583e526a9 (diff)
downloademacs-92ffe44834b8f77ee3f4d37edfdb19f30a376869.tar.gz
emacs-92ffe44834b8f77ee3f4d37edfdb19f30a376869.tar.bz2
emacs-92ffe44834b8f77ee3f4d37edfdb19f30a376869.zip
Body of dynamic let-bindings is not in tail position
This fixes a known bug in `named-let`. * lisp/emacs-lisp/cl-macs.el (cl--self-tco): Prevent TCO from inside dynamic variable bindings. * test/lisp/emacs-lisp/cl-macs-tests.el (cl-macs--labels): Add test.
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/cl-macs.el11
1 files changed, 8 insertions, 3 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index f78fdcf0085..9e93e8775d5 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -2139,9 +2139,14 @@ Like `cl-flet' but the definitions can refer to previous ones.
;; setq the fresh new `ofargs' vars instead ;-)
(let ((shadowings
(mapcar (lambda (b) (if (consp b) (car b) b)) bindings)))
- ;; If `var' is shadowed, then it clearly can't be
- ;; tail-called any more.
- (not (memq var shadowings)))))
+ (and
+ ;; If `var' is shadowed, then it clearly can't be
+ ;; tail-called any more.
+ (not (memq var shadowings))
+ ;; If any of the new bindings is a dynamic
+ ;; variable, the body is not in tail position.
+ (not (cl-some #'macroexp--dynamic-variable-p
+ shadowings))))))
`(,(car exp) ,bindings . ,(funcall opt-exps exps)))
((and `(condition-case ,err-var ,bodyform . ,handlers)
(guard (not (eq err-var var))))