Subject: Re: bug#67795: [PATCH] Handle local-variable major-mode remaps specifying non-existent mode

From: Stefan Monnier <[email-masked]>
Date: Tue, 05 Mar 2024 02:01:25 -0500

I also had time to look at the first hunk, and the "good start"
I proposed wasn't right.

The patch below should be much more than just a "good start", because
I think I got to understand the code this time around :-)
The previous code worked OK but was inconsistent in its handling of
modes that we don't have (i.e. is non-existent).

When `set-auto-mode` does is go through a list of potential candidates
and uses the first one that can be used.  For each candidates, there are
several possibilities:

A. This is the major mode already activated and `keep-mode-if-same` is
   set, so we should do nothing *AND* we should stop right here.
B. The candidate is nil (absent) or is a function we don't have.
   We should skip it and try further candidates.
   This was done for some candidates but not all.
C. The candidate exists: activate it.

So I changed `set-auto-mode-0` to handle B (and return nil in that case)
so that B work consistently for all the candidates and so that
the `functionp` test is applied after remapping rather than before.

But nil was the value returned for A, so I changed that to `:keep`, so it
can be distinguished from B and C.

Then I massaged the `set-auto-mode` code so as to call `set-auto-mode-0`
according to these new rules, which arguably makes the code a bit
simpler (instead of using a `done` variable that we constantly set and
then test, it's just one big `or` where each arm returns the equivalent
of `done`).

        Stefan

* lisp/files.el (set-auto-mode-0): Return `:keep` rather than nil if
the mode is already set and we decided to keep it.
Skip the mode (and return nil) if its function (after remapping) is missing.
(set-auto-mode): Don't test `functionp` any more since
`set-auto-mode-0` does it for us now.
Restructure the code to account for the new behavior of `set-auto-mode-0`,
mostly by replacing the `done` variable with a big `or`.
(hack-local-variables--find-variables): Simplify the (eq handle-mode t)
code so we don't bother building a list, and make it test the
remapped function rather than the mode name instead.