Subject: Re: bug#43116: 27.1; with-eval-after-load executes BODY multiple times for fortran

From: Alan Mackenzie <[email-masked]>
Date: 31 Aug 2020 11:34:28 -0000

Hello, Nonax.

In article <[email-masked]> you wrote:
> Hello,

> The following command will reproduce the bug: emacs -Q -l mwe.el f.f

> f.f does not have to exist, it just serves to open a buffer and enable
> fortran-mode.  The file mwe.el contains the following:

> (with-eval-after-load 'fortran
>   (if (boundp 'fortran-canary)
>       (message "..is cursed.")
>     (message "FORTRAN.."))
>   (defvar fortran-canary t))
> ;;; end of mwe.el

> The following message will appear in the *Message* buffer:
> FORTRAN..
> ..is cursed.

> suggesting BODY has been executed twice.  This problem seems to persist
> across multiple versions of Emacs.  It seems to only apply to fortran
> specifically, however.  I could not reproduce it with other features.

> Kind regards,
> N.

> In GNU Emacs 27.1 (build 1, x86_64-redhat-linux-gnu, GTK+ Version
> 3.24.21, cairo version 1.16.0)
>  of 2020-08-20 built on buildvm-x86-24.iad2.fedoraproject.org
> Windowing system distributor 'Fedora Project', version 11.0.12008000
> System Description: Fedora 32 (Workstation Edition)

[ .... ]

Diagnosis:

1. At a fairly low level, (load "fortran") gets called.
2. In fortran.el L658 in (defvar fortran-mode-map ....) there's a form
  ,(custom-menu-create 'fortran).  This gets evaluated during the load.
3. custom-menu-create's call stack (pertinent part) looks like:
   (do-after-load-evaluation "path/to/fortran.elc")
   (require 'fortran)         <=========================================
   (custom-load-symbol 'fortran)
   (custom-menu-create 'fortran)
4. The above do-after-load-evaluation eventually calls the fortran
   eval-after-load function that outputs "FORTRAN..".
5. At a later stage of the load, do-after-load-evaluation gets called by
   load normally.  This calls the eval-after-load function again, which
   outputs "..is cursed.".

In a nutshell, the problem is the recursive (require 'fortran) called
from within (load "fortran").

I don't yet have any idea on how to fix this bug.

-- 
Alan Mackenzie (Nuremberg, Germany).