Subject: 31.0.50; `setq-local` makes the var buffer-local too soon

From: Stefan Monnier <[email-masked]>
Date: Fri, 21 Feb 2025 08:45:03 -0500

Package: Emacs
Version: 31.0.50

Po Lu has just pointed me to a bug in `setq-local` which shows up when
you do something like:

    (setq-local my-foo (progn (defvar my-foo 1000) my-foo))

Commit afd088bd608 added a workaround for exactly this problem in one of
the uses of `setq-local`.

The problem is that `setq-local` does, fundamentally

    (make-local-variable 'my-foo)
    (let ((val (progn (defvar my-foo 1000) my-foo)))
      (setq my-foo val)

so that during the computation of `val`, the variable has already been
made buffer-local but has not yet been assigned.  So the `defvar` will
correctly define the default value of `my-foo` but `my-foo` will still
be unbound in the current-buffer.

I suggest we change the ordering to:

    (let ((val (progn (defvar my-foo 1000) my-foo)))
      (make-local-variable 'my-foo)
      (setq my-foo val)

As for how to implement that fix.  The simplest way is to just change
the macro, of course.  But maybe a better way is to do it by introducing
a `set-local` function (sibling to `set` and `set-default`) and then
make the macro expand to a call to this function.

When I discussed this with Po Lu he felt this was a risky subtle change
which would interfere with a lot of code.  I was quite surprised at this
reaction because my own gut feeling is that, while it is undoubtedly
a subtle change, it's just a very straightforward bug-fix, highly
unlikely to introduce problems.

WDYT?

        Stefan