Subject: bug#5293: 23.1; unload-feature on buffer-local hooks

From: Stefan Monnier <[email-masked]>
Date: Mon, 06 Apr 2020 14:06:02 -0400

> @@ -299,7 +299,11 @@ unload-feature
>                              ;; Known abnormal hooks etc.
>  			    (memq x unload-feature-special-hooks)))
>  	       (dolist (func removables)
> -	         (remove-hook x func)))))
> +	         (remove-hook x func)
> +                 (save-current-buffer
> +                   (dolist (buffer (buffer-list))
> +                     (set-buffer buffer)
> +                     (remove-hook x func t)))))))
>            ;; Remove any feature-symbols from auto-mode-alist as well.
>            (dolist (func removables)
>              (setq auto-mode-alist

Maybe instead of `(dolist (buffer (buffer-list))` within that big
`mapatoms` within `(dolist (func removables)` (which is O(B*F*V) where
B is the number of buffers, F is the number of functions and V is the
number of hook vars), we should instead do it as:

    (dolist (buffer (buffer-list))
      (dolist (varvar (buffer-local-variables buffer))
        (when <var is a hook>
          (dolist (func removables)
            (remove-hook <var> func t)))))

If we need it to go faster maybe we could also arrange for (add-hook
V F ..)  to do (cl-pushnew V (get F 'hooks-where-it-has-been-put)).
So we could do

    (let ((relevant-hooks
           (mapcan (lambda (f) (get F 'hooks-where-it-has-been-put)) funcs)))
      (dolist (buffer (buffer-list))
        (dolist (varvar (buffer-local-variables buffer))
          (when (memq var relevant-hooks)
            (dolist (func removables)
              (remove-hook <var> func t)))))

-- Stefan