Subject: bug#58601: 29.0.50; Infinite loop in byte-compile--first-symbol-with-pos

From: Alan Mackenzie <[email-masked]>
Date: Tue, 18 Oct 2022 17:06:59 +0000

Hello, Basil.

On Tue, Oct 18, 2022 at 19:34:08 +0300, Basil L. Contovounesios wrote:
> Alan Mackenzie [2022-10-18 15:01 +0000] wrote:

> > On Tue, Oct 18, 2022 at 02:24:02 +0300, Basil L. Contovounesios wrote:

> >> I.e. the 'pure' compile-time form has a cycle, and the DFS of
> >> byte-compile--first-symbol-with-pos gets lost.

> > What's a DFS?

> Depth-First Search.

Thanks!

> >> Paraphrasing Stefan, it's acceptable if the compiler mishandles
> >> circular source code, but it should be able to handle circular data.

> > The problem here seems to be feeding macroexp-warn-and-return with data
> > as the FORM argument.

> That's not the problem, because it's just for illustrative purposes.
> Instead of 'arg' being passed unchanged as the FORM argument, it could
> just as well have been `(my-frobnicate ,arg).

That would not loop, since there is a symbol with position there.

> > FORM is intended only to be an executable lisp form.

> `(my-frobnicate ,arg) fits that bill, right?  The end result is the
> same: macroexp-warn-and-return is fed a form containing a cycle, without
> any of the code that gives rise to the form being circular itself.

This would not loop.

> >> I don't know why, but I can reproduce the hang only when the form is inside
> >> ert-deftest+should, and not inside a plain defun.

> > There is a huge concentration of "advanced" features inside those ~20
> > lines of Lisp code.

> Maybe when the compiler detects sufficiently advanced Lisp it should

>   (signal 'indistinguishable-from-magic (list form))

> >  There's eval-and-compile,

> That's just a shortcut: one could equivalently put my-cycle and
> my-identity in a separate file and 'require' it.  The compiler just
> needs to know that my-cycle is pure and my-identity has a
> compiler-macro before reaching their call sites.

> > nconc, a compiler-macro, and ert.  ;-)

> You forgot 'pure'.  We're spoilt for choice!

:-)

> >> Perhaps byte-compile--first-symbol-with-pos needs to employ something
> >> like byte-run--ssp-seen?  Or does ERT somehow come into play?

> > It wouldn't be difficult, just tedious, to add checking for circular
> > lists into byte-compile--first-symbol-with-pos.  But a circular list is
> > an invalid argument for FORM in macorexp-warn-and-return, see above.

> How else should a compiler-macro safely warn about a problematic
> function argument?

by calling the normal byte compiler warning facilities.  If there is a
symbol somewhere in the FORM passed to them, it won't loop, even if it is
a circular list.

You called macroexp-warn-and-return from outside of the byte compiler.
>From within the byte compiler, it cannot generate a loop (see above).

> > There are surely lots of places in Emacs where feeding a circular
> > list as an argument to a function will cause a hang.

> Sure, but a subset of those places should reasonably be expected to not
> hang...

Your circular list containing an ordinary symbol (i.e. without position)
is not going to arise in the byte compiler.

> > At the moment, I'm not in favour of doing anything here.  I don't think
> > there's a bug.

> ...for instance, when dealing with compile-time constants in real-world
> Elisp.

Maybe you could construct an example of a circular list without a symbol
from code being compiled.  Maybe you could cause a warning from a correct
call of macroexp-warn-and-return to loop.  But I'd be surprised.

> Thanks,

> -- 
> Basil

-- 
Alan Mackenzie (Nuremberg, Germany).