diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index 6cce65e2c9b..05ee0615fec 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -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." diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 4fc56ae4b5d..12079e0f53c 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -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) diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 617a0fb1d40..229f1dbb57b 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -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) diff --git a/test/lisp/emacs-lisp/macroexp-tests.el b/test/lisp/emacs-lisp/macroexp-tests.el index 817c5d7be49..91d66986bc6 100644 --- a/test/lisp/emacs-lisp/macroexp-tests.el +++ b/test/lisp/emacs-lisp/macroexp-tests.el @@ -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)