3

Let's consider a minimal example, I take org-narrow-to-subtree as a compiled function, under the hood it calls narrow-to-region, I add simple advice to it:

(defun bark (START END) (message "Bark!"))
(advice-add 'narrow-to-region :before #'bark)

If I call narrow-to-region interactively, the advice obviously works, but if I call org-narrow-to-subtree which in its turn calls (narrow-to-region), it behaves as if there was no advice.

If re-eval the function definition (the same source as the original, only defining it again instead of using the compiled version):

(defun org-narrow-to-subtree ()
  "Narrow buffer to the current subtree."
  (interactive)
  (save-excursion
    (save-match-data
      (org-with-limited-levels
       (narrow-to-region
    (progn (org-back-to-heading t) (point))
    (progn (org-end-of-subtree t t)
           (when (and (org-at-heading-p) (not (eobp))) (backward-char 1))
           (point)))))))

and call org-narrow-to-subtree again, the advice gets called normally.

  1. Why is that?
  2. How do I solve my problem then? How do I add an advice?
Drew
  • 75,699
  • 9
  • 109
  • 225
  • It'll probably involve a macro somewhere, if advice wasn't avaible when compiled it won't work. I'll check it later. – Muihlinn Dec 02 '20 at 09:02
  • 4
    `narrow-to-region` has its own byte code, 125, try `(byte-compile (lambda () (narrow-to-region 1 10)))`, hence after compilation, the function is replaced by its byte code. – xuchunyang Dec 02 '20 at 09:23
  • I think @xuchunyang will be the quickest way to solve it, I'd say that calling your advised function inside two macros compiled before your advise existed are the culprit, so recompiling the function will make it work – Muihlinn Dec 02 '20 at 12:37

1 Answers1

4

This (narrow-to-region) is the exact example covered by Chris Wellon's article The Limits of Emacs Advice. As @xuchunyang has already pointed out, the issue is that this function has its own byte code value, and hence advice does not work when the code is byte-compiled.

You should read the whole article, but I'll quote this:

It turns out narrow-to-region is so special — probably because it’s used very frequently — that it gets its own bytecode. The primitive function call is being compiled away into a single instruction. This means my advice will not be considered in byte-compiled code. Darnit. The same is true for widen (code 126).

phils
  • 48,657
  • 3
  • 76
  • 115
  • Thanks @phils and @xuchunyang. Is it okay if I force a byte-recompilation of `org` upon initialisation of my package? Or it shall be separate question in this SE? – Daniel Vartanov Dec 06 '20 at 10:00
  • It's not clear to me why you're asking that, so maybe ask a separate question with all of the relevant details. – phils Dec 06 '20 at 10:48