Subject: bug#78737: sit-for behavior changes when byte-compiled

From: Daniel Colascione <[email-masked]>
Date: Wed, 11 Jun 2025 07:57:52 -0700

Eli Zaretskii <[email-masked]> writes:

>> From: Daniel Colascione <[email-masked]>
>> Cc: [email-masked],  [email-masked],  [email-masked]
>> Date: Wed, 11 Jun 2025 07:08:45 -0700
>> 
>> Why is it good that read-key-sequence swallows quits but not read-char?
>
> I don't know.  No one does.  maybe there's a good reason for it, maybe
> there was one at some point but there isn't anymore, maybe it's just a
> historical accident.
>
> But being unable to answer such questions doesn't mean changing the
> behavior is safe.  It usually is the other way around, in a program as
> old and complex as |Emacs.
>
>> C-g is an event.  Why should read-event (but not read-key-sequence?)
>> translate one kind of input event (C-g) to an action (signal quit) but
>> return other kinds of events as they're given?
>
> You consider this to be an inconsistency based only on the name of the
> API.  But that's not necessarily the whole contract of the API.  It
> doesn't need to be called get-char-quit-when-c-g to behave like it
> does.
>
> Anyway, I think arguing about this aspect is not useful.  My problem
> is not theoretical, it is practical: how much will break due to these
> changes, and how long will it take us to become aware of the breakage
> and attempt fixing it?

I went through all the uses of read-char, read-char-exclusively, and
read-event in the tree and didn't find anything that'll break if we make
these functions return C-g as an event.  I did some things that worked
marginally better, as I mentioned in my previous message.  It's possible
something breaks, but I haven't seen evidence of breakage yet.

>> What specifically do you think might break here?
>
> Not in those toy examples, but in much larger programs where these are
> used.
>
> And I know what will break.  As I told, we don't have a good set of
> tests for it.  I only know that every time we changed something in
> read_char and its ilk in recent years, we ended up with regressions.

All the more reason to simplify its contract.

>> The higher level function wants to read an event.  That's exactly what
>> this function does now.
>
>> So you're saying it's a good thing that the behavior of the code changes
>> depending on whether it's compiled?
>
> No, I'm saying that in this case it could be minor enough and rare
> enough to fail to outweigh the risks.
>
>> This whole area is full of bugs.  Are we seriously in "fixing bugs is
>> bad because something might change" territory?  In a development branch?
>> With a knob (for now) to revert to the old, broken behavior?
>
> See above: that's not what I'm saying.
>
>> One way to make the code more understandable is to
>> make it consistent and clearly define its contract.  When code has a
>> regular structure, you don't need to keep a thousand special cases in
>> your mind when working on it.  Regularity allows you to substitute
>> reason for memory.  The code is pretty irregular right now.
>
> I agree, but when dealing with old and very complex code that
> thousands of programs rely upon, we need to consider the risks of
> changing the old behavior even if it is somewhat inconsistent.
> Because sometimes an old, known, and minor problem is better than new,
> unknown, and exciting ones.

Yes, and for cases in which we're changing user-visible semantics in a
way that'll break workflows --- like beginning-of-defun, perhaps ---
then I agree with you.  I don't think this particular change belongs to
that category.  I've looked for evidence that would change my mind and
haven't found any yet.  You're right that changes to the input loop are
risky, but they're going to be necessary sooner or later anyway, so
wouldn't you prefer to change simpler code?

Along the same lines, we could get rid of getcjmp too.  I'm not afraid
of rationalizing the contract of read-event or tweaking any other part
of keyboard.c, but that thing and quit_throw_to_read_char are extremely
confusing and do scare me a bit --- all the more reason, in my mind, to
get rid of them, like Gerd wanted to do years ago.  When is the right
time to do that?  It's not like an Emacs 31 release is imminent.