Subject: Re: bug#16818: Acknowledgement (Undo in region after markers in undo history relocated)

From: Barry OReilly <[email-masked]>
Date: Mon, 24 Feb 2014 17:46:11 -0500

> > the general question comes up: how is the undo history meant to
> > know about marker relocations?

> I think the marker adjustment entries in the undo history are
> invalid when a marker is relocated elsewhere. I don't see code to
> deal with that, so how you would like it to happen?

I found the Elisp manual says about moving markers:

  When you do this, be sure you know whether the marker is used
  outside of your program, and, if so, what effects will result from
  moving it--otherwise, confusing things may happen in other parts of
  Emacs.

So if we expand on the guidance as follows:

diff --git a/doc/lispref/markers.texi b/doc/lispref/markers.texi
index 51b87ab..19386d6 100644
--- a/doc/lispref/markers.texi
+++ b/doc/lispref/markers.texi
@@ -344,10 +344,12 @@ specify the insertion type, create them with
insertion type
 @section Moving Marker Positions

   This section describes how to change the position of an existing
-marker.  When you do this, be sure you know whether the marker is used
-outside of your program, and, if so, what effects will result from
-moving it---otherwise, confusing things may happen in other parts of
-Emacs.
+marker.  When you do this, be sure you know how the marker is used
+outside of your program.  For example, moving a marker to an unrelated
+new position can cause undo to later adjust the marker incorrectly.
+Often when you wish to relocate a marker to an unrelated position, it
+is preferable to make a new marker and set the prior one to point
+nowhere.

 @defun set-marker marker position &optional buffer
 This function moves @var{marker} to @var{position}

then we don't need to worry about markers in general, only the
particular offending ones of the recipe.

As I described, one offending marker is the mark-marker. From the
push-mark function:

(defun push-mark (&optional location nomsg activate)
  [...]
    (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
  [...]
  (set-marker (mark-marker) (or location (point)) (current-buffer))
  [...]
  (setq global-mark-ring (cons (copy-marker (mark-marker))
global-mark-ring))
  )

Two copies are made and the copies go to the mark-ring and
global-mark-ring. The mark continues to be the same marker object
under eq as before, only mutated. Consequently, not only does undo
adjust a marker it shouldn't have, but it doesn't adjust the copies in
the rings when it should have.

What makes more sense to me is that the old value of mark-marker is
pushed onto the rings, then a new marker object is created to become
the value of mark-marker. Then the marker adjustment records would
reference the right markers. Effectively this means the mark would
follow the advice of the Elisp manual excerpt above.

I welcome your guidance about what the right way to solve this bug is.
Thank you.