use-package icon indicating copy to clipboard operation
use-package copied to clipboard

`:after` does not respect `after-load-alist` insertion order

Open hlissner opened this issue 5 years ago • 1 comments

Forgive me if this was intended, but this is something that bites me often, when I use use-package in Doom Emacs. I'll illustrate the issue with these two snippets:

(with-eval-after-load 'foo
  (message "1"))

(use-package foo
  :defer t
  :config (message "2"))

(with-eval-after-load 'foo
  (message "3"))

(require 'foo)  ; #=> prints 1, 2, then 3
(with-eval-after-load 'foo
  (message "1"))

(use-package foo
  :after bar
  :config (message "2"))

(with-eval-after-load 'foo
  (message "3"))

(require 'bar) ; #=> 1, 3, then 2

This is because the use-package block for foo expands to:

(eval-after-load 'bar
  '(progn
     (require 'foo nil nil) ; executes all of `foo's after-load-alist handlers
     (message "2")
     t))

But should it not respect insertion order into after-load-alist? e.g.

(eval-after-load 'foo
  '(message "2"))
(eval-after-load 'bar
  '(progn
     (require 'foo nil nil)
     t))

EDIT: Corrected a couple mistakes in the examples.

hlissner avatar Apr 09 '20 22:04 hlissner

I can confirm I experience the same behavior. While :after does enforce a loading order, the initialization (:init and :config) is essentially inverted in a stack-like fashion:

  • load bar
  • load foo
  • init foo
  • init bar

In my opinion the expected order would be:

  • load bar
  • init bar
  • load foo
  • init foo

The way I understand it, it makes :after useful only as a fancy :defer as the actual initialization order is too confusing for the intended use. The example in the readme does not seem to be practical either as ivy-hydra should require hydra and ivy on its own so :defer t for ivy and hydra should be enough and no external ordering should be needed (possibly with an :ensure caveat but the general use case does seem wrong).

vifon avatar Jan 07 '21 10:01 vifon