Subject: bug#78995: [PATCH] ;;;autoload-expand for special macros

From: "J.D. Smith" <[email-masked]>
Date: Sat, 12 Jul 2025 15:59:44 -0400

Stefan Monnier <[email-masked]> writes:

>>> I've been wanting to add the feature you propose, but this "macro is not
>>> defined" has gotten in the way until now.  I think we need to add
>>> something like a file-local `autoload-requires-for-macros`.
>> How about this solution?  If the car of the following form is not a
>> macro (and not a function), attempt to load the file itself (temporarily
>> expanding `load-path' to include the file's containing directory).  If
>> that fails to define the macro, warn the user, and simply proceed
>> without expansion.
>
> I don't think it's good enough.  Many of the use-cases I've bumped into
> use macros defined in another file (or even another package).

Doesn't a file usually need to require such files/packages in order to
make use of their macros?  Or is the concern that those other
files/packages would not be in the current directory or on the
load-path?  I think package-install installs all requirements first, so
that shouldn't happen for it.

Or perhaps the issue arises in cases like multi-file packages where
`declare-function' is used because you know the load order.  I.e. if:

1. A.el always requires B.el and is its entry point,
2. B.el uses a macro from A.el with an ;;;###autoload-expand, and
3. B.el does _not_ require A.el, only (possibly) mentioning it via
   `declare-function`.

Then loading B.el is, as you say, not good enough.  This is tricky to
work around.

> I think we should aim to provide a mechanism that lets us reduce the
> size of the hardcoded list (ideally to nothing).

There are actually _multiple_ hard-coded lists in
`loaddefs-generate--make-autoload':

1. Macros to expand (by name) and recurse on the expansion.
2. "Function-like operators", which get an `(autoload ...)' form
  created for them.
3. Macros which are known to produce interactive function definitions
   (to set the INTERACTIVE arg for the generated autoload).

What about just mentioning in the docs that using ;;;###autoload-expand
successfully requires that the macro to be expanded is defined upon
loading the containing file?  There is a prominent warning if loading
the file fails to define the macro, so developers should be aware (or
made aware by their users).  They can always, e.g., factor out their
macro to a common file they can require.  The "fallback" is equivalent
to the current behavior: copy the full form into the autoload file.

Otherwise, if a documentation solution is not good enough, we could
create an additional file-local variable that could be consulted if the
user of ;;;###autoload-expand needs to give it some help, e.g.:

- `autoload-macro-expansion-files': a file-local list of additional
  file(s) to load prior to macro expansion, if any macros in calls
  directly preceded by ;;;###autoload-expand are undefined.  A symbol
  `file' in this list indicates the current file.  Defaults to `(file)'.