Subject: bug#54802: OClosure: Make `interactive-form` a generic function

From: Stefan Monnier <[email-masked]>
Date: Mon, 18 Apr 2022 18:59:28 -0400

Eli Zaretskii [2022-04-15 19:14:11] wrote:
> As I said up-thread, I don't understand why we need to touch
> interactive-form at all.

In my experience, OClosures fall into two camps:
- Those, like `advice`, where their interactive form depends on some of
  the data carried by the OClosure.
- Those, like `kmacro`, where all the OClosures of
  that type have the same, constant, interactive form.

For the second group, we can use the current `interactive-form`, with
the only downside that every OClosure of that type will have to carry
its own reference to that same interactive form.

For the first, it's much more problematic: see for example the function
`advice--make-1`.  There we build a new byte-code function with is
a composition of a base function with an advice function.  We currently
do it by hand out of its actual bytecode string, constant vector, ...
The interactive form of the composed function should be a combination of
the interactive forms of the two functions (so that an advice can
advise also the interactive form of a function), which is computed by
`advice--make-interactive-form`.

When working at that level, the interactive form can be computed
dynamically fairly easily, but there are some problems:
- This is messy because we have to dig inside the representation of
  byte code objects.  The use of OClosures would be able to save us
  from that.
- `oclosure.el` can't use the same trick we currently use in
  `advice--make-1` because it lets the byte compiler build the byte-code
  objects for us and the byte-compiler's code doesn't know how to build
  a bytecode object whose interactive-spec is not just an
  immediate constant.
- Doing it like we do in `advice--make-1` computes the interactive form
  too early: if the base function (or the advice function, but that's
  less likely) is an autoloaded function, it will eagerly load the
  file when the advice is applied.  Also if that base function is an
  alias, it will use the interactive form of the current definition of
  the alias and won't be updated if the alias is later redefined.

There are various ways to work around those problems, but the cleanest
fix is to delay the computation of the interactive form to the moment
`interactive-form` is called.

        Stefan