GNU bug report logs - #76470
31.0.50; `setq-local` makes the var buffer-local too soon

Previous Next

Package: emacs;

Reported by: Stefan Monnier <monnier <at> iro.umontreal.ca>

Date: Fri, 21 Feb 2025 13:46:03 UTC

Severity: normal

Found in version 31.0.50

To reply to this bug, email your comments to 76470 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org:
bug#76470; Package emacs. (Fri, 21 Feb 2025 13:46:03 GMT) Full text and rfc822 format available.

Acknowledgement sent to Stefan Monnier <monnier <at> iro.umontreal.ca>:
New bug report received and forwarded. Copy sent to monnier <at> iro.umontreal.ca, bug-gnu-emacs <at> gnu.org. (Fri, 21 Feb 2025 13:46:04 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: bug-gnu-emacs <at> gnu.org
Subject: 31.0.50; `setq-local` makes the var buffer-local too soon
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





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#76470; Package emacs. (Fri, 21 Feb 2025 17:03:03 GMT) Full text and rfc822 format available.

Message #8 received at 76470 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Kangas <stefankangas <at> gmail.com>
To: 76470 <at> debbugs.gnu.org
Cc: monnier <at> iro.umontreal.ca
Subject: Re: bug#76470: 31.0.50;
 `setq-local` makes the var buffer-local too soon
Date: Fri, 21 Feb 2025 17:01:48 +0000
Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of
text editors" <bug-gnu-emacs <at> gnu.org> writes:

> 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.

What are the benefits of adding a new function instead of just changing
the macro?

> 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?

I agree that we should fix the bug.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#76470; Package emacs. (Sun, 23 Feb 2025 21:55:02 GMT) Full text and rfc822 format available.

Message #11 received at 76470 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Stefan Kangas <stefankangas <at> gmail.com>
Cc: 76470 <at> debbugs.gnu.org
Subject: Re: bug#76470: 31.0.50; `setq-local` makes the var buffer-local too
 soon
Date: Sun, 23 Feb 2025 16:54:21 -0500
>> 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.
> What are the benefits of adding a new function instead of just changing
> the macro?

- It adds the function (which is both a benefit and downside
  depending on how you look at it).
- It makes the semantics more clear (this bug wouldn't have occurred if
  I had started with that).
- It opens up the possibility to have a "real" `set-local` which doesn't
  introduce the spurious intermediate state where the var has already
  been made buffer-local but not yet set.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#76470; Package emacs. (Sun, 23 Feb 2025 23:18:02 GMT) Full text and rfc822 format available.

Message #14 received at 76470 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Kangas <stefankangas <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 76470 <at> debbugs.gnu.org
Subject: Re: bug#76470: 31.0.50;
 `setq-local` makes the var buffer-local too soon
Date: Sun, 23 Feb 2025 23:17:22 +0000
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>>> 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.
>> What are the benefits of adding a new function instead of just changing
>> the macro?
>
> - It adds the function (which is both a benefit and downside
>   depending on how you look at it).
> - It makes the semantics more clear (this bug wouldn't have occurred if
>   I had started with that).
> - It opens up the possibility to have a "real" `set-local` which doesn't
>   introduce the spurious intermediate state where the var has already
>   been made buffer-local but not yet set.

OK, sounds good to me.  Thanks.




This bug report was last modified 109 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.