Subject: bug#19383: closed (Re: bug#19383: 25.0.50; query-replace-regexp becomes unusable when using lisp expressions for replacement)

From: [email-masked] (GNU bug Tracking System)
Date: Mon, 15 Dec 2014 23:58:02 +0000

Your bug report

#19383: 25.0.50; query-replace-regexp becomes unusable when using lisp expressions for replacement

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
19383: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=19383
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#19383: 25.0.50; query-replace-regexp becomes unusable when using lisp expressions for replacement
From: Juri Linkov <[email-masked]>
To: Dima Kogan <[email-masked]>
Cc: [email-masked]
Date: Tue, 16 Dec 2014 01:54:53 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

> The issue is that isearch-text-char-description expects a string
> argument, but it's getting bits of that s-expression; specifically
> 'replace-eval-replacement. I haven't looked further, and I don't know if
> this value of the history variables is wrong, or if their parsing is
> incorrect in some way.

Thanks for the detailed report.  This was caused by the recent changes
and is fixed now.

Subject: 25.0.50; query-replace-regexp becomes unusable when using lisp expressions for replacement
From: Dima Kogan <[email-masked]>
To: [email-masked]
Date: Mon, 15 Dec 2014 01:01:28 -0800
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi.

I'm using a bleeding-edge emacs build, compiled from latest source as of
Dec 14. There's a regression in query-replace-regexp where under some
conditions it becomes unable to parse its history, and becomes unusable.

Here's a recipe. Deviating from the exact steps can make the failure not
occur, but I do see this in everyday use, so this isn't exactly a corner
case.

1. Create a file called /tmp/dat. I don't think the contents are super
important. I have

0001
0002
0003
0004
0005
0006
0007
0008

2. emacs -Q /tmp/dat

3. C-M-%
   ^.
   <return>
   \,(concat \#&)
   <return>

   Here we try to do a replacement, but there's an error: (concat ...)
   expects a string, but \#& is a number, and emacs complains. This is
   fine.

4. C-M-%
   <up>
   <end>
   <left>
   <left>
   <backspace>
   <return>
   SPC

   We run another replacement. We pull the previous one from the
   history, and manually remove the # to fix the complaint. \& is a
   string, as desired. We then replace the first match by presing SPC

5. M-%

   Error!

After step 5, trying to M-% or C-M-% always fails with

 mapconcat: Wrong type argument: number-or-marker-p, replace-eval-replacement

This is irreparable without dipping into lisp. Resetting the history
fixes it for the session: (setq query-replace-defaults nil)

When broken, the value of query-replace-defaults is

 (("" replace-eval-replacement replace-quote (concat (match-string 0))) ("^." . "\\,(concat \\#&)"))

and the value of query-replace-history is

 ((replace-eval-replacement replace-quote (concat (match-string 0))) "" "\\,(concat \\#&)" "^.")

The backtrace looks like this:

 Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p replace-eval-replacement)
   isearch-text-char-description(replace-eval-replacement)
   mapconcat(isearch-text-char-description (replace-eval-replacement replace-quote (concat (match-string 0))) "")
   query-replace-descr((replace-eval-replacement replace-quote (concat (match-string 0))))
   #[(from-to) "\302@!	\302A!Q\207" [from-to separator query-replace-descr] 4](("" replace-eval-replacement replace-quote (concat (match-string 0))))
   mapcar(#[(from-to) "\302@!	\302A!Q\207" [from-to separator query-replace-descr] 4] (("" replace-eval-replacement replace-quote (concat (match-string 0))) ("^." . "\\,(concat \\#&)")))
   query-replace-read-from("Query replace" nil)
   query-replace-read-args("Query replace" nil)
   (let ((common (query-replace-read-args (concat "Query replace" (if current-prefix-arg (if (eq current-prefix-arg ...) " backward" " word") "") (if (and transient-mark-mode mark-active) " in region" "")) nil))) (list (nth 0 common) (nth 1 common) (nth 2 common) (if (and transient-mark-mode mark-active) (region-beginning)) (if (and transient-mark-mode mark-active) (region-end)) (nth 3 common)))
   call-interactively(query-replace nil nil)
   command-execute(query-replace)

The issue is that isearch-text-char-description expects a string
argument, but it's getting bits of that s-expression; specifically
'replace-eval-replacement. I haven't looked further, and I don't know if
this value of the history variables is wrong, or if their parsing is
incorrect in some way.

Thanks