GNU bug report logs - #68818
[PATCH] lisp/emacs-lisp/inline.el: Autoload public macros

Previous Next

Package: emacs;

Reported by: Ihor Radchenko <yantar92 <at> posteo.net>

Date: Tue, 30 Jan 2024 13:20:01 UTC

Severity: normal

Tags: patch

Done: Stefan Monnier <monnier <at> iro.umontreal.ca>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 68818 in the body.
You can then email your comments to 68818 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 30 Jan 2024 13:20:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ihor Radchenko <yantar92 <at> posteo.net>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Tue, 30 Jan 2024 13:20:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: bug-gnu-emacs <at> gnu.org
Subject: [PATCH] lisp/emacs-lisp/inline.el: Autoload public macros
Date: Tue, 30 Jan 2024 13:21:51 +0000
[Message part 1 (text/plain, inline)]
Tags: patch

Hello,

This patch solves annoying problem with `define-inline' forms not being
indented correctly unless inline.el is explicitly loaded.

For illustration, try to open the following foo.el file:

(define-inline org-element-type-p (node types)
  "Return non-nil when NODE type is one of TYPES.
TYPES can be a type symbol or a list of symbols."
  (if (inline-const-p types)
      (if (listp (inline-const-val types))
          (inline-quote (memq (org-element-type ,node t) ,types))
        (inline-quote (eq (org-element-type ,node t) ,types)))
    (inline-letevals (node types)
      (inline-quote
       (if (listp ,types)
           (memq (org-element-type ,node t) ,types)
         (eq (org-element-type ,node t) ,types))))))

with emacs -Q, indenting the file will yield different results with and
without executing (require 'inline).

With the patch, indentation becomes consistent.

In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.24.39, cairo version 1.18.0) of 2024-01-28 built on localhost
Repository revision: 5e9ef5d65aea4c278bb58cfc84ea22e7983385da
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12101010
System Description: Gentoo Linux

Configured using:
 'configure JAVAC=/etc/java-config-2/current-system-vm/bin/javac'

[0001-lisp-emacs-lisp-inline.el-Autoload-public-macros.patch (text/patch, attachment)]
[Message part 3 (text/plain, inline)]
-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 30 Jan 2024 14:11:02 GMT) Full text and rfc822 format available.

Message #8 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Ihor Radchenko <yantar92 <at> posteo.net>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Tue, 30 Jan 2024 16:09:52 +0200
> From: Ihor Radchenko <yantar92 <at> posteo.net>
> Date: Tue, 30 Jan 2024 13:21:51 +0000
> 
> This patch solves annoying problem with `define-inline' forms not being
> indented correctly unless inline.el is explicitly loaded.
> 
> For illustration, try to open the following foo.el file:
> 
> (define-inline org-element-type-p (node types)
>   "Return non-nil when NODE type is one of TYPES.
> TYPES can be a type symbol or a list of symbols."
>   (if (inline-const-p types)
>       (if (listp (inline-const-val types))
>           (inline-quote (memq (org-element-type ,node t) ,types))
>         (inline-quote (eq (org-element-type ,node t) ,types)))
>     (inline-letevals (node types)
>       (inline-quote
>        (if (listp ,types)
>            (memq (org-element-type ,node t) ,types)
>          (eq (org-element-type ,node t) ,types))))))
> 
> with emacs -Q, indenting the file will yield different results with and
> without executing (require 'inline).
> 
> With the patch, indentation becomes consistent.

Hmm, I wonder whether there's a less heavy-handed approach to this.

Stefan, any suggestions?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 30 Jan 2024 14:31:01 GMT) Full text and rfc822 format available.

Message #11 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: Ihor Radchenko <yantar92 <at> posteo.net>, 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Tue, 30 Jan 2024 09:30:36 -0500
>> This patch solves annoying problem with `define-inline' forms not being
>> indented correctly unless inline.el is explicitly loaded.
>> 
>> For illustration, try to open the following foo.el file:
>> 
>> (define-inline org-element-type-p (node types)
>>   "Return non-nil when NODE type is one of TYPES.
>> TYPES can be a type symbol or a list of symbols."
>>   (if (inline-const-p types)
>>       (if (listp (inline-const-val types))
>>           (inline-quote (memq (org-element-type ,node t) ,types))
>>         (inline-quote (eq (org-element-type ,node t) ,types)))
>>     (inline-letevals (node types)
>>       (inline-quote
>>        (if (listp ,types)
>>            (memq (org-element-type ,node t) ,types)
>>          (eq (org-element-type ,node t) ,types))))))

[ Side note: IIRC the above can be simplified as:

    (define-inline org-element-type-p (node types)
      "Return non-nil when NODE type is one of TYPES.
    TYPES can be a type symbol or a list of symbols."
      (inline-letevals (node types)
        (if (listp (inline-const-val types))
            (inline-quote (memq (org-element-type ,node t) ,types))
          (inline-quote (eq (org-element-type ,node t) ,types)))))

]

>> with emacs -Q, indenting the file will yield different results with and
>> without executing (require 'inline).
>> With the patch, indentation becomes consistent.
> Hmm, I wonder whether there's a less heavy-handed approach to this.

Agreed.  Also, I think this problem is not specific to `define-inline`.
Maybe the indentation code should try and (auto)load the macros
it encounters.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 30 Jan 2024 16:22:02 GMT) Full text and rfc822 format available.

Message #14 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Tue, 30 Jan 2024 16:24:25 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

> [ Side note: IIRC the above can be simplified as:
>
>     (define-inline org-element-type-p (node types)
>       "Return non-nil when NODE type is one of TYPES.
>     TYPES can be a type symbol or a list of symbols."
>       (inline-letevals (node types)
>         (if (listp (inline-const-val types))
>             (inline-quote (memq (org-element-type ,node t) ,types))
>           (inline-quote (eq (org-element-type ,node t) ,types)))))

Thanks!
`inline-const-val' docstring does not make it clear what happens when
the value is not known at compile time.

>>> with emacs -Q, indenting the file will yield different results with and
>>> without executing (require 'inline).
>>> With the patch, indentation becomes consistent.
>> Hmm, I wonder whether there's a less heavy-handed approach to this.
>
> Agreed.  Also, I think this problem is not specific to `define-inline`.
> Maybe the indentation code should try and (auto)load the macros
> it encounters.

But how does it know that a given (expr ...) is a macro call or a
function call without loading the containing library? AFAIK, only
autoloading can provide such information.

Maybe, autoloading can automatically collect information about all the
symbols defined in each library - whether they are a
function/variable/macro and their declare statement?

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 30 Jan 2024 18:12:02 GMT) Full text and rfc822 format available.

Message #17 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Tue, 30 Jan 2024 13:11:06 -0500
> Thanks!
> `inline-const-val' docstring does not make it clear what happens when
> the value is not known at compile time.

Indeed, the docstring is lacking. 🙁
It "fails" which means that we revert to the "fallback" of not inlining.

>>>> with emacs -Q, indenting the file will yield different results with and
>>>> without executing (require 'inline).
>>>> With the patch, indentation becomes consistent.
>>> Hmm, I wonder whether there's a less heavy-handed approach to this.
>>
>> Agreed.  Also, I think this problem is not specific to `define-inline`.
>> Maybe the indentation code should try and (auto)load the macros
>> it encounters.
>
> But how does it know that a given (expr ...) is a macro call or a
> function call without loading the containing library? AFAIK, only
> autoloading can provide such information.

The autoload of `define-inline` says that it's a macro, so I was
thinking that maybe when the indentation code see `define-inline` it
could `autoload-do-load`.

> Maybe, autoloading can automatically collect information about all the
> symbols defined in each library - whether they are a
> function/variable/macro and their declare statement?

The point of an autoload object is that it's *much* cheaper than the
real thing.  So we can't add very much info to them.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 30 Jan 2024 19:01:01 GMT) Full text and rfc822 format available.

Message #20 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Tue, 30 Jan 2024 19:03:36 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>> But how does it know that a given (expr ...) is a macro call or a
>> function call without loading the containing library? AFAIK, only
>> autoloading can provide such information.
>
> The autoload of `define-inline` says that it's a macro, so I was
> thinking that maybe when the indentation code see `define-inline` it
> could `autoload-do-load`.

That would make sense, yes.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 23 Feb 2025 01:01:02 GMT) Full text and rfc822 format available.

Message #23 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Kangas <stefankangas <at> gmail.com>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 23 Feb 2025 01:00:22 +0000
Ihor Radchenko <yantar92 <at> posteo.net> writes:

> Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>
>>> But how does it know that a given (expr ...) is a macro call or a
>>> function call without loading the containing library? AFAIK, only
>>> autoloading can provide such information.
>>
>> The autoload of `define-inline` says that it's a macro, so I was
>> thinking that maybe when the indentation code see `define-inline` it
>> could `autoload-do-load`.
>
> That would make sense, yes.

Did you make any progress here?  Does it still make sense to keep this
bug report open?  Thanks in advance.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 23 Feb 2025 09:51:01 GMT) Full text and rfc822 format available.

Message #26 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Kangas <stefankangas <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 23 Feb 2025 09:50:02 +0000
Stefan Kangas <stefankangas <at> gmail.com> writes:

>>> The autoload of `define-inline` says that it's a macro, so I was
>>> thinking that maybe when the indentation code see `define-inline` it
>>> could `autoload-do-load`.
>>
>> That would make sense, yes.
>
> Did you make any progress here?  Does it still make sense to keep this
> bug report open?  Thanks in advance.

Did you expect me to update Elisp indentation code?
If yes, I am not really sure where I should do it.
Should it be `lisp-indent-function'?

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 08 Jun 2025 09:45:01 GMT) Full text and rfc822 format available.

Message #29 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Kangas <stefankangas <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Monnier <monnier <at> iro.umontreal.ca>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 08 Jun 2025 09:42:49 +0000
Ihor Radchenko <yantar92 <at> posteo.net> writes:
>> Did you make any progress here?  Does it still make sense to keep this
>> bug report open?  Thanks in advance.
>
> Did you expect me to update Elisp indentation code?
> If yes, I am not really sure where I should do it.
> Should it be `lisp-indent-function'?

Ping!

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 24 Jun 2025 20:56:02 GMT) Full text and rfc822 format available.

Message #32 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Tue, 24 Jun 2025 16:55:08 -0400
>>> Did you make any progress here?  Does it still make sense to keep this
>>> bug report open?  Thanks in advance.
>> Did you expect me to update Elisp indentation code?
>> If yes, I am not really sure where I should do it.
>> Should it be `lisp-indent-function'?
> Ping!

I think that would be the place, yes.
Maybe we could start with a simpler case: indentation inside
`ert-deftest` is currently broken if `ert.el` is not yet loaded.
Yet Emacs already knows that it's an (autoloaded) macro, so it clearly
can DTRT here by (auto)loading the file when indenting something
relative to it.

For `inline-letevals` the situation is a bit more complicated because
the indentation code first needs to see that we're inside
a `define-inline`, but hopefully the above will be a good first step to
tackle the more complex case.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sat, 08 Nov 2025 15:45:01 GMT) Full text and rfc822 format available.

Message #35 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sat, 08 Nov 2025 15:43:55 +0000
[Message part 1 (text/plain, inline)]
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>>> Should it be `lisp-indent-function'?
>
> I think that would be the place, yes.
> Maybe we could start with a simpler case: indentation inside
> `ert-deftest` is currently broken if `ert.el` is not yet loaded.
> Yet Emacs already knows that it's an (autoloaded) macro, so it clearly
> can DTRT here by (auto)loading the file when indenting something
> relative to it.

This will be something like the attached.
However, I am not sure if manually resolving function indirection is the
right approach. I copied it from `function-get', which almost does what
we need as is with AUTOLOAD='macro (but not really, as it does not
trigger autoloading when symbol already has the requested property).

Maybe resolving function indirection should be exposed as auxiliary
function for all Elisp programs?

[tentative.diff (text/x-patch, inline)]
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index e4dfc7c2f78..2b975b340b5 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -1253,6 +1253,17 @@ lisp-indent-function
       (let ((function (buffer-substring (point)
 					(progn (forward-sexp 1) (point))))
 	    method)
+        ;; When FUNCTION is autoloaded macro, trigger autoloading
+        ;; the whole containing library.  See bug#68818.
+        (let ((f (intern-soft function)))
+          (when (macrop f)
+            (while (and (symbolp f) (fboundp f))
+              (let ((fundef (symbol-function f)))
+                (if (and (autoloadp fundef)
+                         (not (equal fundef (autoload-do-load fundef f 'macro))))
+                    nil ; done
+                  ;; resolve alises further
+                  (setq f fundef))))))
 	(setq method (or (function-get (intern-soft function)
                                        'lisp-indent-function)
 			 (get (intern-soft function) 'lisp-indent-hook)))
[Message part 3 (text/plain, inline)]
-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Mon, 10 Nov 2025 12:30:02 GMT) Full text and rfc822 format available.

Message #38 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Mon, 10 Nov 2025 07:29:20 -0500
> This will be something like the attached.
> However, I am not sure if manually resolving function indirection is the
> right approach. I copied it from `function-get', which almost does what
> we need as is with AUTOLOAD='macro

Oh, indeed we should use `function-get`.

> (but not really, as it does not trigger autoloading when symbol
> already has the requested property).

Sorry, I don't understand what you tried to say here.
Did you maybe write one "not" too many?

> Maybe resolving function indirection should be exposed as auxiliary
> function for all Elisp programs?

You mean like `indirect-function`?


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sat, 15 Nov 2025 21:30:02 GMT) Full text and rfc822 format available.

Message #41 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sat, 15 Nov 2025 21:29:12 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>> (but not really, as it does not trigger autoloading when symbol
>> already has the requested property).
>
> Sorry, I don't understand what you tried to say here.
> Did you maybe write one "not" too many?

(autoloadp (symbol-function 'ert-deftest)) ; => t
(function-get 'ert-deftest 'lisp-indent-function 'macro) ; => 2
(autoloadp (symbol-function 'ert-deftest)) ; => t (still t; nothing got autoloaded)
(function-get 'ert-deftest 'i-do-not-exist 'macro) ; => nil
(autoloadp (symbol-function 'ert-deftest)) ; => nil (`function-get' only does autoloading when it cannot find property inside autoload object itself)

>> Maybe resolving function indirection should be exposed as auxiliary
>> function for all Elisp programs?
>
> You mean like `indirect-function`?

Yeah. Obviously, you are right.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 16 Nov 2025 13:00:03 GMT) Full text and rfc822 format available.

Message #44 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 16 Nov 2025 12:59:14 +0000
[Message part 1 (text/plain, inline)]
Ihor Radchenko <yantar92 <at> posteo.net> writes:

>> You mean like `indirect-function`?
>
> Yeah. Obviously, you are right.

See the attached patch.
[0001-lisp-mode-Autoload-macros-before-processing-their-in.patch (text/x-patch, inline)]
From 14f4251aecfe6591018b0371eb3f194f2c6a62cd Mon Sep 17 00:00:00 2001
Message-ID: <14f4251aecfe6591018b0371eb3f194f2c6a62cd.1763297871.git.yantar92 <at> posteo.net>
From: Ihor Radchenko <yantar92 <at> posteo.net>
Date: Sun, 16 Nov 2025 13:50:34 +0100
Subject: [PATCH] lisp-mode: Autoload macros before processing their
 indentation (bug#68818)

* lisp/emacs-lisp/lisp-mode.el (lisp-indent-function): When indenting a
macro, autoload it.  This will make sure that all other macros in the
same library will also be autoloaded, making their indentation rules
active.

Other macros may or may not be necessary, strictly speaking,
but autoloading them is a useful heuristics.
---
 lisp/emacs-lisp/lisp-mode.el | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index e4dfc7c2f78..8cc960c6c47 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -1253,6 +1253,9 @@ lisp-indent-function
       (let ((function (buffer-substring (point)
 					(progn (forward-sexp 1) (point))))
 	    method)
+        ;; When FUNCTION is autoloaded macro, trigger autoloading
+        ;; the whole containing library.  See bug#68818.
+        (autoload-do-load (indirect-function (intern-soft function)) 'macro)
 	(setq method (or (function-get (intern-soft function)
                                        'lisp-indent-function)
 			 (get (intern-soft function) 'lisp-indent-hook)))
-- 
2.50.1

[Message part 3 (text/plain, inline)]
-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 16 Nov 2025 13:47:02 GMT) Full text and rfc822 format available.

Message #47 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 16 Nov 2025 08:46:18 -0500
Ihor Radchenko [2025-11-15 21:29:12] wrote:
> Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>>> (but not really, as it does not trigger autoloading when symbol
>>> already has the requested property).
>> Sorry, I don't understand what you tried to say here.
>> Did you maybe write one "not" too many?
>
> (autoloadp (symbol-function 'ert-deftest)) ; => t
> (function-get 'ert-deftest 'lisp-indent-function 'macro) ; => 2
> (autoloadp (symbol-function 'ert-deftest)) ; => t (still t; nothing got autoloaded)
> (function-get 'ert-deftest 'i-do-not-exist 'macro) ; => nil
> (autoloadp (symbol-function 'ert-deftest)) ; => nil (`function-get' only
> does autoloading when it cannot find property inside autoload object itself)

OK, then what I didn't understand is why you think that's a problem?

> --- a/lisp/emacs-lisp/lisp-mode.el
> +++ b/lisp/emacs-lisp/lisp-mode.el
> @@ -1253,6 +1253,9 @@ lisp-indent-function
>        (let ((function (buffer-substring (point)
>  					(progn (forward-sexp 1) (point))))
>  	    method)
> +        ;; When FUNCTION is autoloaded macro, trigger autoloading
> +        ;; the whole containing library.  See bug#68818.
> +        (autoload-do-load (indirect-function (intern-soft function)) 'macro)
>  	(setq method (or (function-get (intern-soft function)
>                                         'lisp-indent-function)
>  			 (get (intern-soft function) 'lisp-indent-hook)))

AFAICT, if we add `macro` to `function-get` we'll get the same behavior
except that it will not autoload when `lisp-indent-function` is
already set.

Why do we want to autoload when `lisp-indent-function` is already set?


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 16 Nov 2025 14:38:01 GMT) Full text and rfc822 format available.

Message #50 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 16 Nov 2025 14:37:41 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>> (autoloadp (symbol-function 'ert-deftest)) ; => t
>> (function-get 'ert-deftest 'lisp-indent-function 'macro) ; => 2
>> (autoloadp (symbol-function 'ert-deftest)) ; => t (still t; nothing got autoloaded)
>> (function-get 'ert-deftest 'i-do-not-exist 'macro) ; => nil
>> (autoloadp (symbol-function 'ert-deftest)) ; => nil (`function-get' only
>> does autoloading when it cannot find property inside autoload object itself)
>
> OK, then what I didn't understand is why you think that's a problem?
> ...
> AFAICT, if we add `macro` to `function-get` we'll get the same behavior
> except that it will not autoload when `lisp-indent-function` is
> already set.
>
> Why do we want to autoload when `lisp-indent-function` is already set?

As a consequence of the above, if we do
(function-get (intern-soft function) 'lisp-indent-function 'macro)
when function is ert-deftest, other macros from ert library will not be
loaded.

Recall your earlier message:

>>> Maybe we could start with a simpler case: indentation inside
>>> `ert-deftest` is currently broken if `ert.el` is not yet loaded.
>>> Yet Emacs already knows that it's an (autoloaded) macro, so it clearly
>>> can DTRT here by (auto)loading the file when indenting something
>>> relative to it.

What you asked will not happen when we simply try to pass 'macro to
function-get. AFAIU, there is no problem with indentation rules for
ert-deftest itself. The problem is that indentation is wrong for all
other macros (not autoloaded) in ert.el.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 16 Nov 2025 15:35:02 GMT) Full text and rfc822 format available.

Message #53 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 16 Nov 2025 10:34:30 -0500
> As a consequence of the above, if we do
> (function-get (intern-soft function) 'lisp-indent-function 'macro)
> when function is ert-deftest, other macros from ert library will not be
> loaded.

Why not?  (get 'ert-deftest 'lisp-indent-function) gives nil for me, so
the `function-get` would autoload `ert.el`, after which indentation
seems to work fine.  What am I missing?


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Sun, 16 Nov 2025 15:56:02 GMT) Full text and rfc822 format available.

Message #56 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 16 Nov 2025 15:55:34 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>> As a consequence of the above, if we do
>> (function-get (intern-soft function) 'lisp-indent-function 'macro)
>> when function is ert-deftest, other macros from ert library will not be
>> loaded.
>
> Why not?  (get 'ert-deftest 'lisp-indent-function) gives nil for me, so
> the `function-get` would autoload `ert.el`, after which indentation
> seems to work fine.  What am I missing?

(function-get 'ert-deftest 'lisp-indent-function 'macro) ; => 2
(autoloadp (symbol-function 'ert-deftest)) ; => still t

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Mon, 17 Nov 2025 00:56:02 GMT) Full text and rfc822 format available.

Message #59 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Sun, 16 Nov 2025 19:55:10 -0500
Ihor Radchenko [2025-11-16 15:55:34] wrote:
> Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>>> As a consequence of the above, if we do
>>> (function-get (intern-soft function) 'lisp-indent-function 'macro)
>>> when function is ert-deftest, other macros from ert library will not be
>>> loaded.
>> Why not?  (get 'ert-deftest 'lisp-indent-function) gives nil for me, so
>> the `function-get` would autoload `ert.el`, after which indentation
>> seems to work fine.  What am I missing?
> (function-get 'ert-deftest 'lisp-indent-function 'macro) ; => 2
> (autoloadp (symbol-function 'ert-deftest)) ; => still t

That's not what I see here.

[...]

Hmm... apparently (get 'ert-deftest 'lisp-indent-function) returns
2 already at startup in Emacs-30.1, but nil in Emacs `master`.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Mon, 17 Nov 2025 13:13:01 GMT) Full text and rfc822 format available.

Message #62 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Mon, 17 Nov 2025 08:11:59 -0500
Stefan Monnier [2025-11-16 19:55:10] wrote:
> Ihor Radchenko [2025-11-16 15:55:34] wrote:
>> Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>>>> As a consequence of the above, if we do
>>>> (function-get (intern-soft function) 'lisp-indent-function 'macro)
>>>> when function is ert-deftest, other macros from ert library will not be
>>>> loaded.
>>> Why not?  (get 'ert-deftest 'lisp-indent-function) gives nil for me, so
>>> the `function-get` would autoload `ert.el`, after which indentation
>>> seems to work fine.  What am I missing?
>> (function-get 'ert-deftest 'lisp-indent-function 'macro) ; => 2
>> (autoloadp (symbol-function 'ert-deftest)) ; => still t
> That's not what I see here.
>
> [...]
>
> Hmm... apparently (get 'ert-deftest 'lisp-indent-function) returns
> 2 already at startup in Emacs-30.1, but nil in Emacs `master`.

I'm not sure what caused this change.  I suspect it's an unintended
side-effect of the "autoload-macro expand" feature, affecting macros
defined with `cl-defmacro`.

In any case, maybe we want something like the patch below?


        Stefan


diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 05ee0615fec..d0bfcc3647c 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -247,6 +247,12 @@ 'byte-run--set-function-type
             ''function-type (list 'quote val))))
 
 ;; Add any new entries to info node `(elisp)Declare Form'.
+(defalias 'byte-run--dont-autoload
+  (lambda (fn)
+    (lambda (&rest args)
+      (let ((code (apply fn args)))
+        (list 'progn ':autoload-end code)))))
+
 (defvar defun-declarations-alist
   (list
    (list 'advertised-calling-convention
@@ -375,6 +381,9 @@ macro-declarations-alist
     ;; during autoload generation of forms calling them.  See
     ;; `loaddefs-generate--make-autoload'.
     (list 'autoload-macro #'byte-run--set-autoload-macro)
+    ;; Override the entry from `defun-declarations-alist', because we
+    ;; prefer to autoload the macro when trying to indent it (bug#68818).
+    (list 'indent (byte-run--dont-autoload #'byte-run--set-indent))
     (cons
      (list 'no-font-lock-keyword #'byte-run--set-no-font-lock-keyword)
      defun-declarations-alist)))
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 0756c0f908f..e91587b5b23 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -861,7 +861,7 @@ lisp-indent-offset
   :type '(choice (const nil) integer)
   :safe (lambda (x) (or (null x) (integerp x))))
 
-(defcustom lisp-indent-function 'lisp-indent-function
+(defcustom lisp-indent-function #'lisp-indent-function
   "A function to be called by `calculate-lisp-indent'.
 It indents the arguments of a Lisp function call.  This function
 should accept two arguments: the indent-point, and the
@@ -1256,7 +1256,7 @@ lisp-indent-function
 					(progn (forward-sexp 1) (point))))
 	    method)
 	(setq method (or (function-get (intern-soft function)
-                                       'lisp-indent-function)
+                                       'lisp-indent-function 'macro)
 			 (get (intern-soft function) 'lisp-indent-hook)))
 	(cond ((or (eq method 'defun)
                    ;; Check whether we are in flet-like form.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Mon, 17 Nov 2025 14:17:02 GMT) Full text and rfc822 format available.

Message #65 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Mon, 17 Nov 2025 09:16:04 -0500
[Message part 1 (text/plain, inline)]
> In any case, maybe we want something like the patch below?

Or rather like the one below which doesn't immediately crash,


        Stefan
[indent-macro.patch (text/x-diff, inline)]
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 05ee0615fec..47bafbde03e 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -246,6 +246,12 @@ 'byte-run--set-function-type
       (list 'function-put (list 'quote f)
             ''function-type (list 'quote val))))
 
+(defalias 'byte-run--dont-autoload
+  #'(lambda (fn)
+      #'(lambda (&rest args)
+          (let ((code (apply fn args)))
+            (list 'progn ':autoload-end code)))))
+
 ;; Add any new entries to info node `(elisp)Declare Form'.
 (defvar defun-declarations-alist
   (list
@@ -368,16 +374,18 @@ 'byte-run--parse-declarations
         (cons actions cl-decls))))
 
 (defvar macro-declarations-alist
-  (cons
-   (list 'debug #'byte-run--set-debug)
-   (cons
+  (nconc
+   (list
+    (list 'debug #'byte-run--set-debug)
     ;; macros can declare (autoload-macro expand) to request expansion
     ;; during autoload generation of forms calling them.  See
     ;; `loaddefs-generate--make-autoload'.
     (list 'autoload-macro #'byte-run--set-autoload-macro)
-    (cons
-     (list 'no-font-lock-keyword #'byte-run--set-no-font-lock-keyword)
-     defun-declarations-alist)))
+    ;; Override the entry from `defun-declarations-alist', because we
+    ;; prefer to autoload the macro when trying to indent it (bug#68818).
+    (list 'indent (byte-run--dont-autoload #'byte-run--set-indent))
+    (list 'no-font-lock-keyword #'byte-run--set-no-font-lock-keyword))
+   defun-declarations-alist)
   "List associating properties of macros to their macro expansion.
 Each element of the list takes the form (PROP FUN) where FUN is a function.
 For each (PROP . VALUES) in a macro's declaration, the FUN corresponding
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 0756c0f908f..e91587b5b23 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -861,7 +861,7 @@ lisp-indent-offset
   :type '(choice (const nil) integer)
   :safe (lambda (x) (or (null x) (integerp x))))
 
-(defcustom lisp-indent-function 'lisp-indent-function
+(defcustom lisp-indent-function #'lisp-indent-function
   "A function to be called by `calculate-lisp-indent'.
 It indents the arguments of a Lisp function call.  This function
 should accept two arguments: the indent-point, and the
@@ -1256,7 +1256,7 @@ lisp-indent-function
 					(progn (forward-sexp 1) (point))))
 	    method)
 	(setq method (or (function-get (intern-soft function)
-                                       'lisp-indent-function)
+                                       'lisp-indent-function 'macro)
 			 (get (intern-soft function) 'lisp-indent-hook)))
 	(cond ((or (eq method 'defun)
                    ;; Check whether we are in flet-like form.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Mon, 17 Nov 2025 21:03:02 GMT) Full text and rfc822 format available.

Message #68 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Ihor Radchenko <yantar92 <at> posteo.net>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Mon, 17 Nov 2025 21:02:49 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>> In any case, maybe we want something like the patch below?
>
> Or rather like the one below which doesn't immediately crash,

Works in my testing.
Also, with the original issue I reported for inline.el.

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68818; Package emacs. (Tue, 18 Nov 2025 22:35:02 GMT) Full text and rfc822 format available.

Message #71 received at 68818 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Ihor Radchenko <yantar92 <at> posteo.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, Stefan Kangas <stefankangas <at> gmail.com>,
 68818 <at> debbugs.gnu.org
Subject: Re: bug#68818: [PATCH] lisp/emacs-lisp/inline.el: Autoload public
 macros
Date: Tue, 18 Nov 2025 17:34:24 -0500
> Works in my testing.
> Also, with the original issue I reported for inline.el.

Thanks, pushed to `master`,


        Stefan





bug closed, send any further explanations to 68818 <at> debbugs.gnu.org and Ihor Radchenko <yantar92 <at> posteo.net> Request was from Stefan Monnier <monnier <at> iro.umontreal.ca> to control <at> debbugs.gnu.org. (Wed, 19 Nov 2025 13:28:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Thu, 18 Dec 2025 12:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 3 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.