From a8b43e98c592c84957ea304a0dc2d6423af9c5c5 Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Thu, 23 Nov 2017 21:57:09 -0500 Subject: [PATCH] Fix command repetition with lexical-binding (Bug#29334) `call-interactively' relies on analyzing the source of `interactive' forms in order to preserve arguments like (region-end) in the command history, rather than just storing the resulting position. However, the byte-compiler does not preserve the source of the interactive form when lexical-binding is in effect, because `call-interactively' would evaluate the form with dynamic binding in that case. To fix this, change `call-interactively' so that it checks compiled functions for lexical-binding as well. Then the byte-compiler can preserve the source of interactive forms regardless of the value of lexical-binding. * src/callint.c (Fcall_interactively): Functions compiled with lexical-binding have their arglist encoded as an integer, use this to choose the right kind of binding for compiled functions too. * lisp/emacs-lisp/bytecomp.el (byte-compile-lambda): Preserve the uncompiled form of the interactive form when lexical-binding is enabled too. --- lisp/emacs-lisp/bytecomp.el | 6 +----- src/callint.c | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 590db570c5..e16405f09b 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2823,11 +2823,7 @@ byte-compile-lambda (while (consp (cdr form)) (setq form (cdr form))) (setq form (car form))) - (if (and (eq (car-safe form) 'list) - ;; The spec is evalled in callint.c in dynamic-scoping - ;; mode, so just leaving the form unchanged would mean - ;; it won't be eval'd in the right mode. - (not lexical-binding)) + (if (eq (car-safe form) 'list) nil (setq int `(interactive ,newform))))) ((cdr int) diff --git a/src/callint.c b/src/callint.c index 5d88082e38..48ea9ba7a3 100644 --- a/src/callint.c +++ b/src/callint.c @@ -356,7 +356,9 @@ DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0, /* Compute the arg values using the user's expression. */ specs = Feval (specs, CONSP (funval) && EQ (Qclosure, XCAR (funval)) - ? CAR_SAFE (XCDR (funval)) : Qnil); + ? CAR_SAFE (XCDR (funval)) + : COMPILEDP (funval) && INTEGERP (AREF (funval, COMPILED_ARGLIST)) + ? Qt : Qnil); if (events != num_input_events || !NILP (record_flag)) { /* We should record this command on the command history. */ -- 2.11.0