Subject: bug#66750: Unhelpful text in C-h v for variables with a lambda form as value

From: Alan Mackenzie <[email-masked]>
Date: Sat, 28 Oct 2023 19:59:36 +0000

Hello, Stefan.

On Sat, Oct 28, 2023 at 15:13:16 -0400, Stefan Monnier wrote:
> >> I like the idea of keeping better track of the origin of lambda
> >> expressions (tho, admittedly, the same problem occurs with other kinds
> >> of data: I have several times been faced with a keymap or a char-table,
> >> wondering where the heel it came from).
> > Maybe something similar might be possible for those type of objects.

> [ Hmm... food for thought...  ]

> >> I took a look at

> >>     git log -p main..origin/feature/named-lambdas

> >> but that's 127kB, so ... could [you] briefly describe the overall design
> >> (IOW, how it's seen by ELisp programmers, byte-compiler hackers, and
> >> ELisp users)?

> > Certainly.  Each lambda expression has (usually) a defun within which it
> > is defined.  Sometimes it's in a defvar, or defcustom.  That
> > @dfn{defining symbol} is recorded in the lambda form in one of three
> > ways:
> > (i) For a cons form, it's (cadr form), a new field inserted between the
> >   symbol `lambda' and the argument list.
> > (ii) For a byte-compiled form, it's (aref form 5), this new field going
> >   after the doc string and before any interactive form in the compiled
> >   form.

> These two change the visible representation of functions, so I wouldn't
> be surprised if they break some odd hack out there.

There were a few in the test suite I had to amend.

> For (i), do we actually care enough to keep that info (IME the
> functions are usually compiled, and if they're not the code itself
> usually makes it fairly easy to find the code's origin)?

I considered that for some time, and in the end thought that on grounds
of consistency it would be better to put the defining symbol into the
list form as well.

> For (ii), why did you choose slot 5, thus moving the interactive-form
> slot?

Because an interactive form of nil means "(interactive)" with no
arguments.  Only an absent (aref form 6) means there isn't an interactive
form.  So it had to stay as the last slot.

> > There are lots of detailed changes in eval.c and bytecomp.el (and
> > friends).  Also the macro `lambda' in subr.el has been amended to insert
> > the current global defining-symbol if there isn't already a non-nil
> > symbol in that position.

> So the source code can manually provide this extra symbol in `lambda`?
> Where have you found that useful?

The first few functions in debug-early.el and byte-run.el, for a start.
There, there is not yet a defmacro macro.  Also in
comp-trampoline-compile, where there doesn't seem to be any other way to
get the name of the primitive into the defining symbol.  I think there'll
be quite a few other places, too.

> >> Also, what other approaches have you considered/tried and what were the
> >> problems you've encountered, if any?
> > feature/named-lambdas was originally intended for use in backtraces.
> > For the current bug, I've considered individually replacing each lambda
> > with a named defun, so that C-h v will show that name rather than an

> Hmm... as a user, rather than the enclosing definition I think I'd
> expect to get some kind of source information like FILE+LINE+COL.

Possibly: either is a good deal better than what we have at the moment.

> If we give up on keeping that extra info in interpreted functions, the
> FILE+LINE+COL information is readily available to the byte-compiler,
> thanks to that famous Alan guy.

:-)

> Actually, the bytecode functions can already keep the FILE info (in
> the form of the (FILE . OFFSET) cons cell in the docstring slot of the
> bytecode object), we just opt never to expose that FILE info to the user
> (we only use it to fetch the actual docstring).

That's the offset in the .elc file, though, not the source.

> [ Tho, admittedly, it's also that the byte-compiler only uses such
>   (FILE . OFFSET) for named functions, but it wouldn't be hard to change.  ]

> As for how/where to store the LINE+COL, I guess (aref form 5) is still
> an option, although, maybe we should store that info alongside the
> docstring, like we already do for the arglist.

Well, the doc string is at (aref form 4).  :-)

> The way we do it for the arglist is hideous and a pain in the rear (I
> blame the maintainers who accepted my patch back then), so it would be
> an opportunity to "do it right" this time.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).