25.3; compiled commands don't respect special interactive expressions

OpenSubmitted by Allen Li.
Details
6 participants
  • Drew Adams
  • Eli Zaretskii
  • Stefan Monnier
  • Noam Postavsky
  • Glenn Morris
  • Allen Li
Owner
unassigned
Severity
normal
A
A
Allen Li wrote on 17 Nov 2017 07:17
(address . bug-gnu-emacs@gnu.org)
CAJr1M6fEjAkrvDuGZS=XvAm8w6raDmsE6TPyq89mQbJcewfUNw@mail.gmail.com
Repro:
1. emacs -Q2. Mark some text in the buffer3. M-x append-to-buffer RET *scratch* RET4. C-x ESC ESC
Expected last command:
(append-to-buffer "*scratch*" (region-beginning) (region-end))
Actual last command:
(append-to-buffer "*scratch*" 1 145)
If you then go and re-evaluate append-to-buffer (thus loading thesource version instead of the compiled version, you get
(append-to-buffer "*scratch*" (region-beginning) (region-end))
Thus, it looks like the compiled command doesn't handle specialinteractive forms correctly.
D
D
Drew Adams wrote on 17 Nov 2017 15:55
07ace48b-93b3-4b01-9f71-b69ed44492c6@default
Toggle quote (21 lines)> 1. emacs -Q> 2. Mark some text in the buffer> 3. M-x append-to-buffer RET *scratch* RET> 4. C-x ESC ESC> > Expected last command:> > (append-to-buffer "*scratch*" (region-beginning) (region-end))> > Actual last command:> > (append-to-buffer "*scratch*" 1 145)> > If you then go and re-evaluate append-to-buffer (thus loading the> source version instead of the compiled version, you get> > (append-to-buffer "*scratch*" (region-beginning) (region-end))> > Thus, it looks like the compiled command doesn't handle special> interactive forms correctly.
Yes, thank you! This is something that has bugged mefor a while. This change is actually a regression (orelse on purpose?), introduced in Emacs 24. In allEmacs releases prior to 24 it works as a user expects.
Dunno whether this bug report might be a duplicate. Itseems unlikely that no one (including me) has reportedthis before. It reduces the utility of `C-x ESC ESC'considerably.
An inexperienced user will likely give up altogethertrying to use such a command with `C-x ESC ESC', ifnot give up on `C-x ESC ESC' entirely, through notfully understanding. And an experienced user hasthe annoyance of having to edit the hard-coded valuesto get the behavior expected.
G
G
Glenn Morris wrote on 21 Nov 2017 20:15
control message for bug 29334
(address . control@debbugs.gnu.org)
E1eHE1C-0005aE-Ll@fencepost.gnu.org
found 29334 24.4
G
G
Glenn Morris wrote on 21 Nov 2017 20:45
Re: bug#29334: 25.3; compiled commands don't respect special interactive expressions
(name . Allen Li)(address . vianchielfaura@gmail.com)(address . 29334@debbugs.gnu.org)
h4o9nvl8kk.fsf@fencepost.gnu.org
Allen Li wrote:
Toggle quote (13 lines)> 1. emacs -Q> 2. Mark some text in the buffer> 3. M-x append-to-buffer RET *scratch* RET> 4. C-x ESC ESC>> Expected last command:>> (append-to-buffer "*scratch*" (region-beginning) (region-end))>> Actual last command:>> (append-to-buffer "*scratch*" 1 145)
Bisected to a46481370, our old friend "Use lexical-binding".
N
N
Noam Postavsky wrote on 24 Nov 2017 04:11
(name . Glenn Morris)(address . rgm@gnu.org)
87efooz7z8.fsf@users.sourceforge.net
tags 29334 + patchquit
Glenn Morris <rgm@gnu.org> writes:
Toggle quote (2 lines)> Bisected to a46481370, our old friend "Use lexical-binding".
How about this:
From a8b43e98c592c84957ea304a0dc2d6423af9c5c5 Mon Sep 17 00:00:00 2001From: Noam Postavsky <npostavs@gmail.com>Date: Thu, 23 Nov 2017 21:57:09 -0500Subject: [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 commandhistory, rather than just storing the resulting position. However,the byte-compiler does not preserve the source of the interactive formwhen lexical-binding is in effect, because `call-interactively' wouldevaluate the form with dynamic binding in that case.
To fix this, change `call-interactively' so that it checks compiledfunctions for lexical-binding as well. Then the byte-compiler canpreserve the source of interactive forms regardless of the value oflexical-binding.
* src/callint.c (Fcall_interactively): Functions compiled withlexical-binding have their arglist encoded as an integer, use this tochoose the right kind of binding for compiled functions too.* lisp/emacs-lisp/bytecomp.el (byte-compile-lambda): Preserve theuncompiled form of the interactive form when lexical-binding isenabled too.--- lisp/emacs-lisp/bytecomp.el | 6 +----- src/callint.c | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-)
Toggle diff (34 lines)diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.elindex 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.cindex 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
E
E
Eli Zaretskii wrote on 24 Nov 2017 08:58
(name . Noam Postavsky)(address . npostavs@users.sourceforge.net)
83vai09kgq.fsf@gnu.org
Toggle quote (25 lines)> From: Noam Postavsky <npostavs@users.sourceforge.net>> Date: Thu, 23 Nov 2017 22:11:23 -0500> Cc: 29334@debbugs.gnu.org, Allen Li <vianchielfaura@gmail.com>> > > Bisected to a46481370, our old friend "Use lexical-binding".> > How about this:> > >From a8b43e98c592c84957ea304a0dc2d6423af9c5c5 Mon Sep 17 00:00:00 2001> From: Noam Postavsky <npostavs@gmail.com>> 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.
Thanks. If no objections are voiced to this approach, please push itto the master branch. I think this is too radical for the releasebranch.
P.S. Should this change be reflected in the ELisp manual somehow?
N
N
Noam Postavsky wrote on 24 Nov 2017 13:17
(name . Eli Zaretskii)(address . eliz@gnu.org)
877eufzx8p.fsf@users.sourceforge.net
Eli Zaretskii <eliz@gnu.org> writes:
Toggle quote (9 lines)>> 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.>> Thanks. If no objections are voiced to this approach, please push it> to the master branch. I think this is too radical for the release> branch.
Hah, okay, but that was the conservative approach! The radical onewould be resolving this FIXME:
static void fix_command (Lisp_Object input, Lisp_Object values) { /* FIXME: Instead of this ugly hack, we should provide a way for an interactive spec to return an expression/function that will re-build the args without user intervention. */
Toggle quote (2 lines)> P.S. Should this change be reflected in the ELisp manual somehow?
I don't see where.
N
N
Noam Postavsky wrote on 4 Jan 2018 03:56
(name . Eli Zaretskii)(address . eliz@gnu.org)
87d12qs55z.fsf@users.sourceforge.net
tags 29334 fixedclose 29334 27.1quit
Noam Postavsky <npostavs@users.sourceforge.net> writes:
Toggle quote (11 lines)> Eli Zaretskii <eliz@gnu.org> writes:>>>> 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.>>>> Thanks. If no objections are voiced to this approach, please push it>> to the master branch. I think this is too radical for the release>> branch.
Pushed to master.
[1: ce48658191]: 2018-01-03 20:51:28 -0500 Fix command repetition with lexical-binding (Bug#29334) https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=ce48658191befb7734a7af484e368af5ed8b9447
S
S
Stefan Monnier wrote on 4 Jan 2018 06:25
(name . Drew Adams)(address . drew.adams@oracle.com)
jwv4lo2436z.fsf-monnier+bug#29334@gnu.org
Toggle quote (4 lines)> Yes, thank you! This is something that has bugged me> for a while. This change is actually a regression (or> else on purpose?), introduced in Emacs 24.
Indeed. As for the question in parenthesis, yes I consciously decidedto break this "ugly hack" back then, wondering how much time it wouldtake for people to notice it (and hoping I'd find the time/motivationto "do it right" in the mean time).
Toggle quote (10 lines)> Hah, okay, but that was the conservative approach! The radical one> would be resolving this FIXME:>> static void> fix_command (Lisp_Object input, Lisp_Object values)> {> /* FIXME: Instead of this ugly hack, we should provide a way for an> interactive spec to return an expression/function that will re-build the> args without user intervention. */
E.g. we could allow the interactive spec to return either a list ofargument *values*, or a list of argument *expressions* (and we coulddistinguish the two by having the second be a vector instead of a list,for example).

Stefan
N
N
Noam Postavsky wrote on 7 Jan 2018 03:55
(name . Eli Zaretskii)(address . eliz@gnu.org)
87bmi6qsxg.fsf@users.sourceforge.net
notfixed 29334 27.1reopen 29334tag 29334 - fixed patchquit
Noam Postavsky <npostavs@users.sourceforge.net> writes:
Toggle quote (6 lines)> Pushed to master.>> [1: ce48658191]: 2018-01-03 20:51:28 -0500> Fix command repetition with lexical-binding (Bug#29334)> https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=ce48658191befb7734a7af484e368af5ed8b9447
Turns out this doesn't actually work, so I've reverted it.
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29988#11
?