1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-15 10:30:25 -08:00

Fix local defvar scoping error (bug#46387)

This bug was introduced by the lexical variable constant propagation
mechanism.  It was discovered by Michael Heerdegen.

* lisp/emacs-lisp/byte-opt.el (byte-optimize-let-form)
(byte-optimize-body): Let the effects of a local defvar declaration be
scoped by let and let*, not any arbitrary Lisp expression body (such
as progn).
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--get-vars)
(bytecomp-local-defvar): New test.
This commit is contained in:
Mattias Engdegård 2021-02-10 14:26:49 +01:00
parent d9af416701
commit f3ae26cb2a
2 changed files with 33 additions and 2 deletions

View file

@ -1168,6 +1168,37 @@ mountpoint (Bug#44631)."
(with-demoted-errors "Error cleaning up directory: %s"
(delete-directory directory :recursive)))))
(defun bytecomp-tests--get-vars ()
(list (ignore-errors (symbol-value 'bytecomp-tests--var1))
(ignore-errors (symbol-value 'bytecomp-tests--var2))))
(ert-deftest bytecomp-local-defvar ()
"Check that local `defvar' declarations work correctly, both
interpreted and compiled."
(let ((lexical-binding t))
(let ((fun '(lambda ()
(defvar bytecomp-tests--var1)
(let ((bytecomp-tests--var1 'a) ; dynamic
(bytecomp-tests--var2 'b)) ; still lexical
(ignore bytecomp-tests--var2) ; avoid warning
(bytecomp-tests--get-vars)))))
(should (listp fun)) ; Guard against overzealous refactoring!
(should (equal (funcall (eval fun t)) '(a nil)))
(should (equal (funcall (byte-compile fun)) '(a nil)))
)
;; `progn' does not constitute a lexical scope for `defvar' (bug#46387).
(let ((fun '(lambda ()
(progn
(defvar bytecomp-tests--var1)
(defvar bytecomp-tests--var2))
(let ((bytecomp-tests--var1 'c)
(bytecomp-tests--var2 'd))
(bytecomp-tests--get-vars)))))
(should (listp fun))
(should (equal (funcall (eval fun t)) '(c d)))
(should (equal (funcall (byte-compile fun)) '(c d))))))
;; Local Variables:
;; no-byte-compile: t
;; End: