From 4f1ce5db12639359822652673aa013345aa2991e Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 18 Aug 2023 19:22:17 -0400 Subject: [PATCH] (Fmake_local_variable): Fix bug#65209 * src/data.c (Fmake_local_variable): Don't delegate to `Fset` since they have to obey `let_shadows_buffer_binding_p` whereas we don't. * test/src/data-tests.el (data-tests--bug65209): New var. (data-tests-make-local-bug65209): New test. --- src/data.c | 19 ++++++++++--------- test/src/data-tests.el | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/data.c b/src/data.c index 619ab8fde64..377bcfce35d 100644 --- a/src/data.c +++ b/src/data.c @@ -2213,17 +2213,18 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */) if (sym->u.s.trapped_write == SYMBOL_NOWRITE) xsignal1 (Qsetting_constant, variable); - if (blv ? blv->local_if_set - : (forwarded && BUFFER_OBJFWDP (valcontents.fwd))) - { - tem = Fboundp (variable); - /* Make sure the symbol has a local value in this particular buffer, - by setting it to the same value it already has. */ - Fset (variable, (EQ (tem, Qt) ? Fsymbol_value (variable) : Qunbound)); - return variable; - } if (!blv) { + if (forwarded && BUFFER_OBJFWDP (valcontents.fwd)) + { + int offset = XBUFFER_OBJFWD (valcontents.fwd)->offset; + int idx = PER_BUFFER_IDX (offset); + eassert (idx); + if (idx > 0) + /* If idx < 0, it's always buffer local, like `mode-name`. */ + SET_PER_BUFFER_VALUE_P (current_buffer, idx, true); + return variable; + } blv = make_blv (sym, forwarded, valcontents); sym->u.s.redirect = SYMBOL_LOCALIZED; SET_SYMBOL_BLV (sym, blv); diff --git a/test/src/data-tests.el b/test/src/data-tests.el index 680fdd57d71..8167cccdd18 100644 --- a/test/src/data-tests.el +++ b/test/src/data-tests.el @@ -768,6 +768,31 @@ comparing the subr with a much slower Lisp implementation." (default-value 'last-coding-system-used)) '(no-conversion bug34318))))) +(defvar-local data-tests--bug65209 :default-value) + +(ert-deftest data-tests-make-local-bug65209 () + (dolist (sym '(data-tests--bug65209 ;A normal always-local Lisp var. + cursor-in-non-selected-windows)) ;Same but DEFVAR_PER_BUFFER. + ;; Note: For vars like `mode-name' that are *really* always buffer-local, + ;; this test isn't right because the `cl-progv' only binds the + ;; buffer-local value! + (let ((default (default-value sym)) + vli vlo vgi vgo) + (with-temp-buffer + (cl-progv (list sym) '(:let-bound-value) + ;; While `setq' would not make the var buffer-local + ;; (because we'd be setq-ing the let-binding instead), + ;; `setq-local' definitely should. + (set (make-local-variable sym) :buffer-local-value) + (setq vgi (with-temp-buffer (symbol-value sym))) + (setq vli (symbol-value sym))) + (setq vgo (with-temp-buffer (symbol-value sym))) + (setq vlo (symbol-value sym))) + (should (equal (list vgo vgi vlo vli) + (cons default + '(:let-bound-value + :buffer-local-value :buffer-local-value))))))) + (ert-deftest data-tests-make_symbol_constant () "Can't set variable marked with 'make_symbol_constant'." (should-error (setq most-positive-fixnum 1) :type 'setting-constant)) -- 2.39.2