Subject: bug#76108: Call `modify_text' only on the text being replaced in `subst-char-in-region'

From: Stefan Monnier <[email-masked]>
Date: Tue, 11 Feb 2025 19:17:44 -0500

>> The `nil 8 21` and `t 8 9 1` are the values I'd expect, but the `17 to
>> 17` seems very odd and the fact that the hook is called at all for the
>> "after" case sounds like a bug, as you point out.
>
> It doesn't change anything but I should make a correction: That first
> case is also an overlay from 14 to 17.

Ah, well it does change things in the sense that it was quite weird.
A copy/paste error is a nice explanation and I can stop worrying
about it. 🙂

> I thought it might have been because `subst-char-in-region' calls
> `signal_after_change' from the first to the last change (and that is
> likely not unrelated) but even if that were the case the first and last
> change in the above situation is the sole newline at the middle, so it
> shouldn't have reached the overlay regardless.  Maybe
> `report_overlay_modification' calls everything called in the before call
> as well, but I honestly can't tell.

It turns out that, indeed, the C code makes extra efforts to call the
same `modification-hooks` functions from overlays before and after
the change, hence the weird behavior (from `editfns.c`):

    /* Lisp vector holding overlay hook functions to call.
       Vector elements come in pairs.
       Each even-index element is a list of hook functions.
       The following odd-index element is the overlay they came from.
    
       Before the buffer change, we fill in this vector
       as we call overlay hook functions.
       After the buffer change, we get the functions to call from this vector.
       This way we always call the same functions before and after the change.  */
    static Lisp_Object last_overlay_modification_hooks;
    
    /* Number of elements actually used in last_overlay_modification_hooks.  */
    static ptrdiff_t last_overlay_modification_hooks_used;

so, while it looks like a bug to me, it's very much done on purpose.
Not sure whether we should fix it or document it.

And I guess we could use the same approach to run the
`modification-hooks` from text properties also *after* the modification.

        Stefan