]> git.eshelyaron.com Git - emacs.git/commitdiff
* src/buffer.c (Fmove_overlay): Don't call Fdelete_overlay
authorStefan Monnier <monnier@iro.umontreal.ca>
Sun, 14 Oct 2018 20:44:21 +0000 (16:44 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Sun, 14 Oct 2018 20:44:21 +0000 (16:44 -0400)
... because the data structure is not in a consistent state.

* test/src/buffer-tests.el (overlay-evaporation-after-killed-buffer):
New test.

src/buffer.c
test/src/buffer-tests.el

index 024e64f0d74a2258e3e243d546cd9d8406b9d541..ac2de7d19f23c93870f3a879efc75a8d924c2400 100644 (file)
@@ -3991,6 +3991,16 @@ buffer.  */)
 
       unchain_both (ob, overlay);
     }
+  else
+    /* An overlay not associated with any buffer will normally have its
+       `next' field set to NULL, but not always: when killing a buffer,
+       we just set its overlays_after and overlays_before to NULL without
+       manually setting each overlay's `next' field to NULL.
+       Let's correct it here, to simplify subsequent assertions.
+       FIXME: Maybe the better fix is to change `kill-buffer'!?  */
+    XOVERLAY (overlay)->next = NULL;
+
+  eassert (XOVERLAY (overlay)->next == NULL);
 
   /* Set the overlay boundaries, which may clip them.  */
   Fset_marker (OVERLAY_START (overlay), beg, buffer);
@@ -4020,10 +4030,20 @@ buffer.  */)
        modify_overlay (b, min (o_beg, n_beg), max (o_end, n_end));
     }
 
+  eassert (XOVERLAY (overlay)->next == NULL);
+
   /* Delete the overlay if it is empty after clipping and has the
      evaporate property.  */
   if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate)))
-    return unbind_to (count, Fdelete_overlay (overlay));
+    { /* We used to call `Fdelete_overlay' here, but it causes problems:
+         - At this stage, `overlay' is not included in its buffer's lists
+           of overlays (the data-structure is in an inconsistent state),
+           contrary to `Fdelete_overlay's assumptions.
+         - Most of the work done by Fdelete_overlay has already been done
+           here for other reasons.  */
+      drop_overlay (XBUFFER (buffer), XOVERLAY (overlay));
+      return unbind_to (count, overlay);
+    }
 
   /* Put the overlay into the new buffer's overlay lists, first on the
      wrong list.  */
index 0e4fd3655ae3911d874724f95498e94ee8a89e67..609585f43ed06d14617ac1b24f9e860f5cc2389d 100644 (file)
@@ -79,4 +79,19 @@ with parameters from the *Messages* buffer modification."
   (with-temp-buffer
     (should (eq (buffer-base-buffer (current-buffer)) nil))))
 
+(ert-deftest overlay-evaporation-after-killed-buffer ()
+  (let* ((ols (with-temp-buffer
+                (insert "toto")
+                (list
+                 (make-overlay (point-min) (point-max))
+                 (make-overlay (point-min) (point-max))
+                 (make-overlay (point-min) (point-max)))))
+         (ol (nth 1 ols)))
+    (overlay-put ol 'evaporate t)
+    ;; Evaporation within move-overlay of an overlay that was deleted because
+    ;; of a kill-buffer, triggered an assertion failure in unchain_both.
+    (with-temp-buffer
+      (insert "toto")
+      (move-overlay ol (point-min) (point-min)))))
+
 ;;; buffer-tests.el ends here