mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-17 10:27:41 +00:00
(eval-and-compile): Preserve the surrounding lexical context
Implement a better fix for bug#79634. * lisp/emacs-lisp/byte-run.el (eval-and-compile): * lisp/emacs-lisp/bytecomp.el (byte-compile-initial-macro-environment) <eval-and-compile>: Preserve the surrounding lexical context (the part available during macroexpansion, i.e. which vars are dynbound). * lisp/emacs-lisp/rx.el (<pcase> rx): Remove workaround. * test/lisp/emacs-lisp/macroexp-tests.el (macroexp--dynbound-eval-and-compile): New test.
This commit is contained in:
parent
48357dc612
commit
4ec24ce2a1
4 changed files with 49 additions and 6 deletions
|
|
@ -683,7 +683,8 @@ enabled."
|
|||
;; When the byte-compiler expands code, this macro is not used, so we're
|
||||
;; either about to run `body' (plain interpretation) or we're doing eager
|
||||
;; macroexpansion.
|
||||
(list 'quote (eval (cons 'progn body) lexical-binding)))
|
||||
(list 'quote (eval (cons 'progn body)
|
||||
(when lexical-binding (or macroexp--dynvars t)))))
|
||||
|
||||
(defun with-no-warnings (&rest body)
|
||||
"Like `progn', but prevents compiler warnings in the body."
|
||||
|
|
|
|||
|
|
@ -589,7 +589,11 @@ Only conses are traversed and duplicated, not arrays or any other structure."
|
|||
macroexpand-all-environment)))
|
||||
(eval (byte-run-strip-symbol-positions
|
||||
(bytecomp--copy-tree expanded))
|
||||
lexical-binding)
|
||||
(when lexical-binding
|
||||
(or (append
|
||||
macroexp--dynvars
|
||||
byte-compile-bound-variables)
|
||||
t)))
|
||||
expanded)))))
|
||||
(with-suppressed-warnings
|
||||
. ,(lambda (warnings &rest body)
|
||||
|
|
|
|||
|
|
@ -1685,10 +1685,6 @@ following constructs:
|
|||
REF can be a number, as usual, or a name
|
||||
introduced by a previous (let REF ...)
|
||||
construct."
|
||||
;; FIXME: We can't rely on the surrounding lexical context because
|
||||
;; `pcase-defmacro' wraps this function inside an `eval-and-compile',
|
||||
;; so we have to repeat the (defvar rx--pcase-vars).
|
||||
(defvar rx--pcase-vars)
|
||||
(let* ((rx--pcase-vars nil)
|
||||
(regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps)))))
|
||||
`(and (pred stringp)
|
||||
|
|
|
|||
|
|
@ -124,6 +124,48 @@
|
|||
(dyn dyn dyn dyn)
|
||||
(dyn dyn dyn lex))))))
|
||||
|
||||
(ert-deftest macroexp--dynbound-eval-and-compile ()
|
||||
(let ((code1 '(progn
|
||||
(eval-and-compile
|
||||
(defun my-foo () (bound-and-true-p my-foo))
|
||||
(defun my-identity (x)
|
||||
(defvar my-foo)
|
||||
(let ((my-foo x))
|
||||
(my-foo))))
|
||||
(defmacro my-toto (y)
|
||||
`(list ',y ',(my-identity y)))
|
||||
(eval-when-compile (my-toto 7))))
|
||||
(code2 '(progn
|
||||
(defvar my-foo)
|
||||
(eval-and-compile
|
||||
(defun my-foo () (bound-and-true-p my-foo))
|
||||
(defun my-identity (x)
|
||||
(let ((my-foo x))
|
||||
(my-foo))))
|
||||
(defmacro my-toto (y)
|
||||
`(list ',y ',(my-identity y)))
|
||||
(eval-when-compile (my-toto 7))))
|
||||
(code3 '(progn
|
||||
(eval-and-compile
|
||||
(defvar my-foo)
|
||||
(defun my-foo () (bound-and-true-p my-foo))
|
||||
(defun my-identity (x)
|
||||
(let ((my-foo x))
|
||||
(my-foo))))
|
||||
(defmacro my-toto (y)
|
||||
`(list ',y ',(my-identity y)))
|
||||
(eval-when-compile (my-toto 7)))))
|
||||
(should (equal (eval code1 t) '(7 7)))
|
||||
(should (equal (eval code2 t) '(7 7)))
|
||||
(should (equal (eval code3 t) '(7 7)))
|
||||
(should (equal (eval (let ((lexical-binding t)) (byte-compile code1)) t)
|
||||
'(7 7)))
|
||||
(should (equal (eval (let ((lexical-binding t)) (byte-compile code2)) t)
|
||||
'(7 7)))
|
||||
(should (equal (eval (let ((lexical-binding t)) (byte-compile code3)) t)
|
||||
'(7 7)))
|
||||
))
|
||||
|
||||
(defmacro macroexp--test-macro1 ()
|
||||
(declare (obsolete "new-replacement" nil))
|
||||
1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue