[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#44733: Nested let bindings for non-local DEFVAR_PER_BUFFER variables

From: Eli Zaretskii
Subject: bug#44733: Nested let bindings for non-local DEFVAR_PER_BUFFER variables unwind wrong
Date: Thu, 19 Nov 2020 16:10:27 +0200

> From: Spencer Baugh <sbaugh@catern.com>
> Date: Wed, 18 Nov 2020 22:11:00 -0500
> However, more buggy is what happens when these let bindings are nested.
> If we do first SPECPDL_LET_DEFAULT, then setq, then a second nested
> SPECPDL_LET_DEFAULT, when the second nested let binding is unwound, the
> default value for variable is set to the pseudo-buffer-local value that
> was active in (current-buffer) when the nested let was entered.
> See the below code example (left-margin is chosen as an arbitrary
> DEFVAR_PER_BUFFER variable):
> (let ((left-margin 1))
>   ;; Set this variable "pseudo-locally", inside a SPECPDL_LET_DEFAULT binding.
>   (setq left-margin 123)
>   (assert (eq left-margin 123))
>   ;; Note, it's not a local variable.
>   (assert (not (local-variable-p 'left-margin)))
>   ;; The default value doesn't change.
>   (assert (eq (default-value 'left-margin) 1))
>   (with-temp-buffer (assert (eq left-margin 1)))
>   ;; Perform a seemingly unrelated do-nothing let-binding of left-margin.
>   (let ((left-margin 2)))
>   ;; !! The default value of left-margin has changed to 123.
>   (assert (eq (default-value 'left-margin) 123))
>   (with-temp-buffer (assert (eq left-margin 123)))
>   ;; Emacs used (current-buffer)'s value for left-margin, 123, instead of
>   ;; the actual default value, 1, when storing the old value for left-margin.
>   ;; So when it unwound the let, it set the default value to 123!
> )
> This seems unexpected.

Why did you think this is a bug?  The ELisp manual seems to document
what you see:

     A variable can have more than one local binding at a time (e.g., if
  there are nested ‘let’ forms that bind the variable).  The “current
  binding” is the local binding that is actually in effect.  It determines
  the value returned by evaluating the variable symbol, and it is the
  binding acted on by ‘setq’.

Or did I misunderstand what you found unexpected?

reply via email to

[Prev in Thread] Current Thread [Next in Thread]