unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Matthew Malcomson <hardenedapple@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 62419@debbugs.gnu.org, Stefan Monnier <monnier@iro.umontreal.ca>
Subject: bug#62419: 28.2; Elisp let-bound buffer-local variable and kill-local-variable
Date: Sat, 25 Mar 2023 16:19:57 +0000	[thread overview]
Message-ID: <36DF2B3B-8E8B-4418-8DBB-A67A1292817A@gmail.com> (raw)
In-Reply-To: <83v8ipcaot.fsf@gnu.org>


> On 25 Mar 2023, at 11:49, Eli Zaretskii <eliz@gnu.org> wrote:
> 
>> From: Matthew Malcomson <hardenedapple@gmail.com>
>> Date: Fri, 24 Mar 2023 13:37:57 +0000
>> 
>> 
>> 
>> I think the final state after having done the above should be:
>> 1) Global value has not changed.
>> 2) Local value has not changed.
>> 
>> While the observed state after the above is:
>> 1) Global value has been set to `other-symbol'.
>> 2) Local value has been removed.
>> 
>> - The `setq` inside the `let` sets the *global* value rather than creating a buffer-local variable.
>> - The `let` on the buffer-local version of the variable is lost.
> 
> What is the purpose of doing this? what are you trying to accomplish,
> and why?
> 

I came across this when looking into that yasnippet bug I linked in my previous email.
This sequence is not performed on purpose.
The let binding and kill-local-variable happen outside that plugins control, and are unexpected.

The specific context is:
When yasnippet minor mode is turned on it records the “original” `auto-fill-function` and replaces it with its own wrapper using `setq`.
It uses the “original” to `funcall` from the wrapper and to resetting when yasnippet minor mode turned off.
Yasnippet sets `auto-fill-function` to its wrapper using ’setq’ to ensure the value is buffer-local.

AIUI the minor mode is usually turned on outside of any let binding, but the described situation happens due to an edge-case:
- `newline` let-binds `auto-fill-mode`
- Visited file has changed outside of emacs, so user is queried whether to `revert-buffer` while in `newline`
- `revert-buffer` calls `normal-mode`, which runs `kill-all-local-variables`
- Later, `yasnippet-mode` is turned on and the `setq` is evaluated.

N.b. The change I’m suggesting only means that whatever was outside the `let` binding is kept.
That implies that there would still likely be some problem edge-case in the yasnippet code.
I’m just raising the bug on the premise that the existing behaviour seems likely to cause harder to debug problems that my suggestion.
I.e. once at the top-level, seeing a `setq` of a buffer-local variable has changed the top-level global value is very surprising to me.
But not seeing the effect of a `setq` because it was performed inside some unexpected `let` binding is less surprising.
So I believe that debugging unexpected behaviour due to the second would be easier than behaviour due to the first.


>> The manual for `make-variable-buffer-local` — in `(elisp) Creating Buffer-Local` — does mention that if a variable is in a `let` binding then a `setq` does not create a buffer-local version.
>> That said, I’m guessing the intention of this behaviour is so a `let` binding on a global variable is modified rather than bypassed by a `setq`.
>> I’d suggest that is not relevant to the above code since the use of `kill-local-variable` means the `let` is effectively lost already (e.g. it does not get “reset” on an unwind).
> 
> Did you also read about default-toplevel-value and
> set-default-toplevel-value (in the "Default Value" node of the ELisp
> manual)?

Honestly I haven’t looked hard into how to fix the bug I was hitting in elisp.
A solution seems like it would have to answer the more general question of what yasnippet should do if it’s minor-mode is turned on while in a `let` binding of `auto-fill-mode`, and I’m not a yasnippet developer.
I'm reporting this on the premise that the elisp behaviour seemed strange enough to me to ask whether it should be different.

> 
>> I’m not proposing this as a change, just including it for extra context about the cause.
>> I *believe* that the form of the C code around here looks like the special case of a forwarded variable not having a buffer-local value but having a buffer-local `let` binding could easily have been an oversight rather than intention.
> 
> Stefan, any comments?






  reply	other threads:[~2023-03-25 16:19 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-24 13:37 bug#62419: 28.2; Elisp let-bound buffer-local variable and kill-local-variable Matthew Malcomson
2023-03-25 11:49 ` Eli Zaretskii
2023-03-25 16:19   ` Matthew Malcomson [this message]
2023-03-26 14:01 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-26 14:34   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-26 15:01   ` Matthew Malcomson
2023-03-26 15:16     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-26 15:30     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-29 10:56       ` Matthew Malcomson
2023-04-02 21:55         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-09-12  0:00           ` Stefan Kangas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=36DF2B3B-8E8B-4418-8DBB-A67A1292817A@gmail.com \
    --to=hardenedapple@gmail.com \
    --cc=62419@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).