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

From: Stefan Monnier <[email-masked]>
Date: Thu, 14 Apr 2022 21:18:58 -0400

>> - It's very brittle since it won't find those commands that have
>>   interactive specs like "r\np" or where it's not a string (like
>>   `kill-region` and many others, actually there are regularly more, e.g.
>>   to make them obey `use-region-p`).
> Hmm, I'll try to adapt that code to those commands.

The "r\np" case is easy to solve: just use (string-match "^r").
But the other case is a lot harder since we're talking about analyzing
arbitrary code, potentially byte-compiled.

>> - That loop signaled an error because of an erroneous autoload in
>>   `gnus.el` (it's now fixed in `master`), so your code probably did
>>   not do that.
> Somehow I never ran into that.

Hmm... odd.  I know the problem doesn't show up if you have
`gnus-score.el` loaded beforehand, but otherwise I wonder how you dodged
that "bullet" (not that it matters, it's fixed now anyway; just curious).

Talking about curious, I wonder what you use that loop for.

>> One reason is that for the case of advice, I'd much rather compute the
>> interactive spec lazily (when the command is called) rather than when
>> the advice is built.
>>
>> Another reason is that there is no dedicated "oclosure slot" for an
>> interactive-spec.  In theory we could use the byte-code object's slot
>> for that, but making it computable (as needed for bug#51695 and for
>> advice) would require significant changes to cconv.el and bytecomp.el
>> (and to make it not too inconvenient to use in `advice.el` it'd
>> additionally require extending the syntax of `interactive`).
>>
>> We could add a dedicated "oclosure slot" for the interactive-spec, but
>> it'd likely be rather ugly, since that would need to be accessed from
>> the C in `cmds.c` but would require testing the type of the OClosure
>> first and that would have to be written in ELisp since it depends on how
>> OClosure types are represented which itself depends on `cl-defstruct`,
>> etc...
> OClosures are records, right?  There's no other record type that can be
> a function with an interactive form, so we could just use `recordp'
> instead of calling into Lisp for that.

They're somewhat like records but they're not `recordp`, they're `functionp`.

> Alternatively, we could try to speed up generic dispatch, but I don't
> know that code and as such am devoid of ideas in that direction.

Part of the 2x slowdown is due to generic dispatch but part is due to
the fact the code is in ELisp rather than in C, so even a "perfectly
fast" generic dispatch wouldn't get us back the factor 2x.
And speeding up generic dispatch is not super easy.

        Stefan