Subject: Re: bug#78221: 31.0.50; Improving *-change-functions notifications

From: Alan Mackenzie <[email-masked]>
Date: Sat, 3 May 2025 14:46:45 +0000

Hello, Eli.

Thanks for including me on the Cc: list.

On Sat, May 03, 2025 at 09:54:33 +0300, Eli Zaretskii wrote:
> > Cc: [email-masked], Alan Mackenzie <[email-masked]>
> > Date: Fri, 02 May 2025 17:48:11 -0400
> > From:  Stefan Monnier via "Bug reports for GNU Emacs,
> >  the Swiss army knife of text editors" <[email-masked]>

> > - Allow *-change-functions notifications to be nested.
> >   E.g. allow a C function to call

> >       BEFORE 10 100
> >         BEFORE 20 30
> >         AFTER 20 25 10
> >       AFTER 10 90 90
> >       AFTER 10 60 80

> >   or something like that.  This would require some way for the C code to
> >   indicate which BEGIN corresponds to which AFTER.  This could happen
> >   for example by adding a "change-ID" to every notification, so we'd
> >   get:

> >       BEFORE nnn 10 100
> >         BEFORE mmm 20 30
> >         AFTER mmm 20 25 10
> >       AFTER nnn 10 90 90
> >       AFTER nnn 10 60 80

> >   I don't know how we could do that in a backward compatible way, and
> >   I can't think of any `*-change-functions` which would benefit from
> >   this nesting (all the ones I can think of would either ignore the
> >   extra info or use the change-ID to distinguish inner notifications
> >   from outer ones and then ignore the inner ones).

> > - Maybe the last point can be turned into an internal change with no
> >   ELisp-side changes: use an approach like the one above but filter out
> >   the inner changes directly in the C code.  This would provide
> >   to ELisp the same behavior that was brought by the fix to bug#78042,
> >   but without resorting to the "hammer" of `inhibit-modification-hooks`
> >   which risks silencing legitimate notifications.

> On the "nested notifications" part of this, I'd like to hear specific
> problems with them.  (I've added to the discussion people who might
> have real-life examples of the problems.)  Specifically, I'm not sure
> I have a good understanding of why they are a problem in the first
> place.  Is it only because of the difficulty to pair BEFORE and AFTER
> notifications? or is there something else?

I think nested invocations of before/after-change functions would be a
bad idea.  It would be bound to increase complexity of bugs in this area
in the future.  It reminds me of one of my proposals from some years ago,
to have a hook called when buffer narrowing changes.  Richard advised me
in no uncertain terms that this would have been just _too_ powerful, and
would have enabled people to do things difficult to debug.  I think
nested b/a-c-functions would be similarly unwise.

Yes, I've had specific problems in this area, in CC Mode.  One difficult
to solve bug involved the setting of font text properties triggering the
change hooks spuriously (and slowing things down a lot).  I can't
remember it all that clearly.  But solving it involved ensuring
inhibit-modification-hooks was correctly set.

> Due to the Emacs's highly-recursive workings and the various hooks we
> have, which are ever-expanding, there's a virtually infinite number of
> situations where some code, called while a buffer-change operation is
> under way, itself calls a buffer-changing primitive, thus generating
> nested notifications.  Finding and fixing all of theses situations one
> by one will take us infinite time, so I would like to consider more
> practical alternatives.  And for that, IMO we need a very good
> understanding of the problems they cause.

As I proposed in my reply to Stefan M., I don't think finding most/all of
these situations need be too difficult.  insdel.c could be temporarily
instrumented to signal an error on detecting an illegitimate buffer
change.  The difficulty here might be false positives, when a program
intends to make buffer changes from inside a change hook function.  I
don't think these are common, though.

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).