[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master f3ae26c: Fix local defvar scoping error (bug#46387)
From: |
Mattias Engdegård |
Subject: |
master f3ae26c: Fix local defvar scoping error (bug#46387) |
Date: |
Wed, 10 Feb 2021 08:47:47 -0500 (EST) |
branch: master
commit f3ae26cb2ae581a84bbaa15a47e9917a799a5682
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>
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.
---
lisp/emacs-lisp/byte-opt.el | 4 ++--
test/lisp/emacs-lisp/bytecomp-tests.el | 31 +++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 4fa2c75..8851f0e 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -698,7 +698,8 @@ Same format as `byte-optimize--lexvars', with shared
structure and contents.")
(append new-lexvars byte-optimize--lexvars))
;; Walk the body expressions, which may mutate some of the records,
;; and generate new bindings that exclude unused variables.
- (let* ((opt-body (byte-optimize-body (cdr form) for-effect))
+ (let* ((byte-optimize--dynamic-vars byte-optimize--dynamic-vars)
+ (opt-body (byte-optimize-body (cdr form) for-effect))
(bindings nil))
(dolist (var let-vars)
;; VAR is (NAME EXPR [KEEP [VALUE]])
@@ -730,7 +731,6 @@ Same format as `byte-optimize--lexvars', with shared
structure and contents.")
;; all-for-effect is true. returns a new list of forms.
(let ((rest forms)
(result nil)
- (byte-optimize--dynamic-vars byte-optimize--dynamic-vars)
fe new)
(while rest
(setq fe (or all-for-effect (cdr rest)))
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el
b/test/lisp/emacs-lisp/bytecomp-tests.el
index bc623d3..0b70c11 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -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:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master f3ae26c: Fix local defvar scoping error (bug#46387),
Mattias Engdegård <=