Subject: bug#78582: 30.1; which-key-mode overwrites custom key bindings

From: Gerd Möllmann <[email-masked]>
Date: Mon, 02 Jun 2025 14:30:29 +0200

Eli Zaretskii <[email-masked]> writes:

>> From: Gerd Möllmann <[email-masked]>
>> Cc: [email-masked],  [email-masked],  [email-masked],
>>   [email-masked]
>> Date: Mon, 02 Jun 2025 10:20:25 +0200
>> 
>> Eli Zaretskii <[email-masked]> writes:
>> 
>> >> From: Gerd Möllmann <[email-masked]>
>> >> Cc: Stefan Monnier <[email-masked]>,  [email-masked],
>> >>   [email-masked],  [email-masked]
>> >> Date: Mon, 02 Jun 2025 09:42:17 +0200
>> >> 
>> >> Eli Zaretskii <[email-masked]> writes:
>> >> 
>> >> >> From: Gerd Möllmann <[email-masked]>
>> >> >> Cc: Alex Murray <[email-masked]>,  Po Lu <[email-masked]>,
>> >> >>   [email-masked]
>> >> >> Date: Mon, 02 Jun 2025 05:49:14 +0200
>> >> >> 
>> >> >> Eli Zaretskii <[email-masked]> writes:
>> >> >> 
>> >> >> > Po Lu, any ideas why the PGTK build could show this strange behavior?
>> >> >> 
>> >> >> I encountered this on macOS today. Reproducer with an installed Emacs 
>> >> >> (which is the Emacs.app on macOS):
>> >> >> 
>> >> >>   ~/Desktop/Emacs.app/Contents/MacOS/Emacs -q
>> >> >> 
>> >> >> In *scratch*, eval
>> >> >> 
>> >> >>  (global-set-key [f4] #'kill-current-buffer)
>> >> >>  (documentation 'rectangle-mark-mode)
>> >> >> 
>> >> >> Then C-h k <f4> and observe that it has been redefined.
>> >> >
>> >> > Not reproducible on my system with today's master branch.  When I
>> >> > press "C-h k <f4>" after evaluating the above line by line, I get the
>> >> > expected documentation of kill-current-buffer.
>> >> 
>> >> It seems to depend on trying this in an installed Emacs, and that that
>> >> Emacs is older than what is built in the repo that I built it in. For
>> >> example, the Emacs I'm running is from some weeks ago when I started
>> >> using the NS freeze workaround I posted to emacs-devel. In the repo, a
>> >> more current Emacs is built.
>> >> 
>> >> >> A backtrace how this happens with which-key is at then end. In short,
>> >> >> which-key calls 'documentation' which loads lisp/loaddefs which
>> >> >> evaluates the global-set-keys loaddefs.el contains.
>> >> >
>> >> > "M-x debug-on-entry RET global-set-key RET" doesn't pop up the
>> >> > debugger when I evaluate "(documentation 'rectangle-mark-mode)".
>> >> >
>> >> > Anyway, why would Emacs want to load loaddefs, when loaddefs is
>> >> > preloaded?
>> >> 
>> >> Could be Fdocumentation:
>> >> 
>> >> doc.c:
>> >>   365   if (FIXNUMP (doc) || (CONSP (doc) && FIXNUMP (XCDR (doc))))
>> >>   366     {
>> >>   367       Lisp_Object tem = get_doc_string (doc, 0);
>> >>   368       if (NILP (tem) && try_reload)
>> >>   369         {
>> >>   370           /* The file is newer, we need to reset the pointers.  */
>> >>   371           reread_doc_file (Fcar_safe (doc));
>> >>   372           try_reload = false;
>> >> 
>> >> 
>> >> doc.c:
>> >>   310 static void
>> >>   311 reread_doc_file (Lisp_Object file)
>> >>   312 {
>> >>   313   if (NILP (file))
>> >>   314     Fsnarf_documentation (Vdoc_file_name);
>> >>   315   else
>> >>   316     save_match_data_load (file, Qt, Qt, Qt, Qnil);
>> >>   317 }
>> >> 
>> >> That's of course not the root cause, but somehow it's happening.
>> >
>> > So you are saying that the problem happens if Emacs is older than its
>> > loaddefs.el?  If so, this is not a situation we support, so I think
>> > this bug is not a bug at all.  When loaddefs is regenerated, one is
>> > supposed to re-dump Emacs.
>> 
>> No that doesn't seem to be the case. In the installed Emacs.app
>> 
>>   /Users/gerd/Desktop/Emacs.app/Contents/MacOS:
>>   -rwxr-xr-x 1 gerd staff 4678640 Jun  1 04:55 Emacs
>> 
>>   -rw-r--r--   1 gerd staff  396932 Jun  1 04:55 loaddefs.el.gz
>>   -rw-r--r--   1 gerd staff 1530577 Jun  1 04:55 loaddefs.elc
>> 
>>   -rw-r--r--   1 gerd staff 991796 Jun  1 04:56 DOC
>> 
>> The timestamps look okay.
>
> But you seemed to be saying that the installed Emacs was for some
> reason loading loaddefs from the repo's worktree, which was newer:

I believe it's loading the loaddefs.el from the installation because of
this part of the backtrace I sent in the first mail

  global-set-key("\30(" kmacro-start-macro)
  byte-code("\300\301\302\303\304$\210\305\302\306\"\210\307\310\311\"\210\307\312\313\"\210\307\314\315\"\210\307\316\317\"\210\307\320\321\"\210\307\322\323\"\210\300\323\324\325\304\326%\210\327\330\331\332#\210\333\330\331\334#\210\300\311\324\335\304$\210\300\313\324\336\304$\210\300\337\324\340\304$\210\300\317\324\341\304$\210\300\321\324\342\304$\210\300\315\324\343\304$\210\300\344\324\345\304$\210\300\346\324\347#\210\300\350\324\351#\210\333\350\346\334#\210\300\352\324\353\304$\210\327\354\355\"\210\300\355\324\356\304$\210\305\324\357\"\207" [autoload kkc-region "kkc" ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 768162) t register-definition-prefixes ("kkc-") global-set-key "\30(" kmacro-start-macro "\30)" kmacro-end-macro "\30e" kmacro-end-and-call-macro [f3] kmacro-start-macro-or-insert-counter [f4] kmacro-end-or-call-macro "\30\13" kmacro-keymap "kmacro" ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 768555) keymap defalias kmacro-exec-ring-item funcall "Execute item ITEM from the macro ring.\nARG is the number of times to execute the item." make-obsolete "29.1" ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 768689) ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 769692) kmacro-call-macro ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 770110) ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 770706) ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 771651) ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 771871) kmacro-end-call-mouse ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 772193) kmacro ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 772352) kmacro-lambda-form ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 772507) kmacro-name-last-macro ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 772549) kmacro-menu list-keyboard-macros ("/Users/gerd/Desktop/Emacs.app/Contents/Resources/lisp/loaddefs.elc" . 772804) ("kmacro-")] 6)
  documentation(rectangle-mark-mode)

which mentions the file. No way to be 100% sure though, and it's not
a debug build, so I can't look.

>
>>> It seems to depend on trying this in an installed Emacs, and that that
>>> Emacs is older than what is built in the repo that I built it in. For
>>> example, the Emacs I'm running is from some weeks ago when I started
>>> using the NS freeze workaround I posted to emacs-devel. In the repo, a
>>> more current Emacs is built.
>
> Did I misunderstand?  My point is that if Emacs for some reason loads
> a newer loaddefs, that is not a situation that is expected.  maybe we
> should understand why that newer loaddefs is being loaded in your
> case.

I don't know what's going on either. When I build a new Emacs.app and
run that (even from the sasme commit ID), the problem does not occur.
When I start the older Emacs.app it does 🤷. Without debug info and
having it in LLDB, it's all guess work.