Subject: bug#74964: 31.0.50 master; .dir-locals.el vars does not work with changing major mode

From: Stefan Monnier <[email-masked]>
Date: Thu, 16 Jan 2025 23:34:34 -0500

> ((nil . ((my/test . "test")
>          (eval . (setq-local my/test2 "test2"))))
>  (c-mode . ((eval . (when (eq major-mode 'c-mode)
>                       (c++-mode))))))

[ Sigh!  This is starting to make me remember the ugly hacks I added to
  try and avoid inf-loops in my type checker.  ]

How 'bout the patch below?

        Stefan
diff --git a/lisp/files.el b/lisp/files.el
index e9f69fcd33c..9981e7083c3 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -4490,15 +4490,15 @@ hack-one-local-variable--obsolete
                      (substitute-command-keys instead)
                    (format-message "use `%s' instead" instead)))))))
 
-(defvar hack-local-variables--inhibit nil
-  "List of file/dir local variables to ignore.")
+(defvar hack-local-variables--inhibit-eval nil
+  "List of `eval' forms to ignore in file/dir local variables.")
 
 (defun hack-one-local-variable (var val)
   "Set local variable VAR with value VAL.
 If VAR is `mode', call `VAL-mode' as a function unless it's
 already the major mode."
   (pcase var
-    ((guard (memq var hack-local-variables--inhibit)) nil)
+    ((and 'eval (guard (memq val hack-local-variables--inhibit-eval))) nil)
     ('mode
      (let ((mode (intern (concat (downcase (symbol-name val))
                                  "-mode"))))
@@ -4506,8 +4506,8 @@ hack-one-local-variable
     ('eval
      (pcase val
        (`(add-hook ',hook . ,_) (hack-one-local-variable--obsolete hook)))
-     (let ((hack-local-variables--inhibit ;; FIXME: Should be buffer-local!
-            (cons 'eval hack-local-variables--inhibit)))
+     (let ((hack-local-variables--inhibit-eval ;; FIXME: Should be buffer-local!
+            (cons val hack-local-variables--inhibit-eval)))
        (save-excursion (eval val t))))
     (_
      (hack-one-local-variable--obsolete var)