Subject: Re: bug#72759: 31.0.50; Emacs hangs with open-paren-in-column-0-is-defun-start set to nil

From: Eshel Yaron <[email-masked]>
Date: Thu, 22 Aug 2024 17:49:22 +0200

Hi,

Eli Zaretskii <[email-masked]> writes:

>> From: Eshel Yaron <[email-masked]>
>> Cc: [email-masked]
>> Date: Thu, 22 Aug 2024 14:37:01 +0200
>> 
>> Eli Zaretskii <[email-masked]> writes:
>> 
>> > Would it make sense to have checkdoc-next-docstring bind
>> > open-paren-in-column-0-is-defun-start to a non-nil value?
>> 
>> Not entirely: the difference in behavior of beginning-of-defun is
>> unexpected, and may prove problematic in other cases as well, so it
>> would be best to fix the root cause IMO.  Namely, in
>> beginning-of-defun-raw, the fallback cond clause fails to move forward
>> over an sexp that does starts after the beginning of the line.
>
> How do you propose to fix the root cause, when Emacs fails to
> correctly identify the beginning of a defun?  Suppose we'd want to fix
> the condition of this loop:
>
>>> (while (and (not (setq found (checkdoc--next-docstring)))
>>>                 (beginning-of-defun -1)))
>
> so it doesn't infloop -- how would you go about that, when
> beginning-of-defun doesn't move and you are not at BOB?

After taking another look, ISTM that the problem is that checkdoc
assumes that beginning-of-defun either advances point or returns nil,
but since beginning-of-defun unconditionally moves to the beginning of
the line, it can in fact find a defun ahead of point (and thus return
non-nil) but then move back to the beginning of the line, so point is
unchanged.  So the assumption in checkdoc doesn't always hold when
open-paren-in-column-0-is-defun-start is nil.  This assumption should
still hold, however, for beginning-of-defun-raw, which doesn't go back
to the beginning of the line.

This suggests the following change, which indeed seems to fix the hang:

diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 949ca6b74ad..65226d8ee44 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -981,7 +981,7 @@ checkdoc-next-docstring
 Return nil if there are no more doc strings."
   (let (found)
     (while (and (not (setq found (checkdoc--next-docstring)))
-                (beginning-of-defun -1)))
+                (beginning-of-defun-raw -1)))
     found))
 
 (defun checkdoc--next-docstring ()