unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Unbinding let-bound built-in variables
       [not found] <87pltdcaa7.fsf.ref@yahoo.com>
@ 2024-05-23  6:28 ` Po Lu
  2024-05-23  7:12   ` Eli Zaretskii
  2024-05-23 14:47   ` Stefan Monnier via Emacs development discussions.
  0 siblings, 2 replies; 17+ messages in thread
From: Po Lu @ 2024-05-23  6:28 UTC (permalink / raw)
  To: emacs-devel

set_internal clears the forwarding pointer of a symbol when the new
value is Qunbound, which is reasonable if the symbol should be globally
bound, but has the undesired effect of disconnecting a symbol's value
from its forwarding pointer when its binding will be reestablished once
a let-binding is unwound:

  (let ((initial-window-system 'foo))
    (makunbound 'initial-window-system)
    initial-window-system) 
  initial-window-system => x

(gdb) p Vinitial_window_system
$1 = XIL(0x834fa10)
(gdb) xsymbol
$2 = (struct Lisp_Symbol *) 0x8fac130
"foo"
  
How do you suggest that this be resolved?  I'm quite loath to introduce
another field in the *fwds holding whether the symbol is bound, or to
save forwarding pointers in specbindings, as either of these solutions
would conflict with another ongoing project of mine (as does the current
arrangement, which I am attempting to eliminate), and strikes me as not
terribly elegant.  Let me also ask whether it is really worth the while
to permit let-bound built-in symbols to be unbound in the first place?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23  6:28 ` Unbinding let-bound built-in variables Po Lu
@ 2024-05-23  7:12   ` Eli Zaretskii
  2024-05-23  7:31     ` Po Lu
  2024-05-23 14:47   ` Stefan Monnier via Emacs development discussions.
  1 sibling, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-05-23  7:12 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Date: Thu, 23 May 2024 14:28:00 +0800
> 
> set_internal clears the forwarding pointer of a symbol when the new
> value is Qunbound, which is reasonable if the symbol should be globally
> bound, but has the undesired effect of disconnecting a symbol's value
> from its forwarding pointer when its binding will be reestablished once
> a let-binding is unwound:
> 
>   (let ((initial-window-system 'foo))
>     (makunbound 'initial-window-system)
>     initial-window-system) 
>   initial-window-system => x
> 
> (gdb) p Vinitial_window_system
> $1 = XIL(0x834fa10)
> (gdb) xsymbol
> $2 = (struct Lisp_Symbol *) 0x8fac130
> "foo"
>   
> How do you suggest that this be resolved?

Why should it be resolved?  What practical problems do you need to
solve that require the technique such as above?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23  7:12   ` Eli Zaretskii
@ 2024-05-23  7:31     ` Po Lu
  2024-05-23  8:08       ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Po Lu @ 2024-05-23  7:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> Why should it be resolved?  What practical problems do you need to
> solve that require the technique such as above?

The problem that it is impossible to protect a built-in variable against
being made unbound, and more importantly, that variables so unbound
become useless without any external indication of the fact, being
ostensibly bound after the let completes and the makunbound is
"reverted".  Knowing of this bug in advance would have spared me an hour
of bewilderment.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23  7:31     ` Po Lu
@ 2024-05-23  8:08       ` Eli Zaretskii
  2024-05-23  9:13         ` Po Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-05-23  8:08 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Cc: emacs-devel@gnu.org
> Date: Thu, 23 May 2024 15:31:11 +0800
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > Why should it be resolved?  What practical problems do you need to
> > solve that require the technique such as above?
> 
> The problem that it is impossible to protect a built-in variable against
> being made unbound, and more importantly, that variables so unbound
> become useless without any external indication of the fact, being
> ostensibly bound after the let completes and the makunbound is
> "reverted".  Knowing of this bug in advance would have spared me an hour
> of bewilderment.

Which code unbinds built-in variables?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23  8:08       ` Eli Zaretskii
@ 2024-05-23  9:13         ` Po Lu
  2024-05-23 10:00           ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Po Lu @ 2024-05-23  9:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> Which code unbinds built-in variables?

New code that is being written?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23  9:13         ` Po Lu
@ 2024-05-23 10:00           ` Eli Zaretskii
  2024-05-23 11:18             ` Po Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-05-23 10:00 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Cc: emacs-devel@gnu.org
> Date: Thu, 23 May 2024 17:13:39 +0800
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > Which code unbinds built-in variables?
> 
> New code that is being written?

Why do something as weird as that?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23 10:00           ` Eli Zaretskii
@ 2024-05-23 11:18             ` Po Lu
  2024-05-23 11:32               ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Po Lu @ 2024-05-23 11:18 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> Why do something as weird as that?

Because it so happened that that was the easiest means of forcing an
access to a variable to signal.  But if it is decided that Emacs does
not support this feature, makunbound should signal an error, rather than
subtly leaving the symbol in this bizarre limbo.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23 11:18             ` Po Lu
@ 2024-05-23 11:32               ` Eli Zaretskii
  0 siblings, 0 replies; 17+ messages in thread
From: Eli Zaretskii @ 2024-05-23 11:32 UTC (permalink / raw)
  To: Po Lu, Stefan Monnier; +Cc: emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Cc: emacs-devel@gnu.org
> Date: Thu, 23 May 2024 19:18:05 +0800
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > Why do something as weird as that?
> 
> Because it so happened that that was the easiest means of forcing an
> access to a variable to signal.  But if it is decided that Emacs does
> not support this feature, makunbound should signal an error, rather than
> subtly leaving the symbol in this bizarre limbo.

Stefan, WDYT about this?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23  6:28 ` Unbinding let-bound built-in variables Po Lu
  2024-05-23  7:12   ` Eli Zaretskii
@ 2024-05-23 14:47   ` Stefan Monnier via Emacs development discussions.
  2024-05-24  1:30     ` Po Lu
  1 sibling, 1 reply; 17+ messages in thread
From: Stefan Monnier via Emacs development discussions. @ 2024-05-23 14:47 UTC (permalink / raw)
  To: emacs-devel

> set_internal clears the forwarding pointer of a symbol when the new
> value is Qunbound, which is reasonable if the symbol should be globally
> bound, but has the undesired effect of disconnecting a symbol's value
> from its forwarding pointer when its binding will be reestablished once
> a let-binding is unwound:

I've been uncomfortable with the part you describe as "reasonable" ever
since I noticed it.  Maybe the best option is to signal an error if you
try to `makunbound` such a forwarded var.

We could also refrain from clearing the forwarding when we `makunbound`,
but my understanding is that we don't want to do that because the
`Qunbound` value might then leak from the C code to ELisp.


        Stefan




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-23 14:47   ` Stefan Monnier via Emacs development discussions.
@ 2024-05-24  1:30     ` Po Lu
  2024-05-24  3:35       ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Po Lu @ 2024-05-24  1:30 UTC (permalink / raw)
  To: Stefan Monnier via Emacs development discussions.; +Cc: Stefan Monnier

Stefan Monnier via "Emacs development discussions."
<emacs-devel@gnu.org> writes:

> I've been uncomfortable with the part you describe as "reasonable" ever
> since I noticed it.

Why?  It's precisely the behavior I would expect from unbinding a
built-in variable.

> Maybe the best option is to signal an error if you try to `makunbound`
> such a forwarded var.
>
> We could also refrain from clearing the forwarding when we `makunbound`,
> but my understanding is that we don't want to do that because the
> `Qunbound` value might then leak from the C code to ELisp.

Isn't Qunbound treated identically by Fsymbol_value and company,
whether its source be a forward or otherwise?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-24  1:30     ` Po Lu
@ 2024-05-24  3:35       ` Stefan Monnier
  2024-05-24  5:38         ` Po Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2024-05-24  3:35 UTC (permalink / raw)
  To: Po Lu; +Cc: Stefan Monnier via Emacs development discussions.

>> I've been uncomfortable with the part you describe as "reasonable" ever
>> since I noticed it.
> Why?  It's precisely the behavior I would expect from unbinding a
> built-in variable.

I'd expect that the connection between the ELisp var and the C var is
"forever", especially since once the connection is broken there's no way
to re-establish it, so I think it's a drastic effect.

In contrast, to me `makunbound` just means "doesn't have a value yet"
and is fairly harmless (not must worse than `setq`).  I'd expect that if
I put the previous value back in, things would be "back to normal",
including the fact that I'll also see the same value on both the C and
the ELisp side.

>> Maybe the best option is to signal an error if you try to `makunbound`
>> such a forwarded var.
>> We could also refrain from clearing the forwarding when we `makunbound`,
>> but my understanding is that we don't want to do that because the
>> `Qunbound` value might then leak from the C code to ELisp.
> Isn't Qunbound treated identically by Fsymbol_value and company,
> whether its source be a forward or otherwise?

I think most code which reads the C side of forwarded vars presumes the
value is not `Qunbound`, so I'd be surprised if there isn't some code
out there which reads such vars and then puts the result somewhere ELisp
can see it.  E.g. if you `(makunbound 'buffer-file-name)` and then call
`(buffer-file-name)`.


        Stefan




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-24  3:35       ` Stefan Monnier
@ 2024-05-24  5:38         ` Po Lu
  2024-05-24 14:10           ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Po Lu @ 2024-05-24  5:38 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Stefan Monnier via Emacs development discussions.

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> I'd expect that the connection between the ELisp var and the C var is
> "forever", especially since once the connection is broken there's no way
> to re-establish it, so I think it's a drastic effect.

Uninterning the variable's name would also produce such a "drastic
effect", at least in code loaded after the fact.

> In contrast, to me `makunbound` just means "doesn't have a value yet"
> and is fairly harmless (not must worse than `setq`).  I'd expect that if
> I put the previous value back in, things would be "back to normal",
> including the fact that I'll also see the same value on both the C and
> the ELisp side.

IMHO, the meaning of `makunbound' is to revert the effect of the
operation that established the binding within the current dynamic scope,
be that a DEFVAR_LISP or a setq.  But all these are details, and my only
wish is to see this decided one way or the other, preferably soon.

> I think most code which reads the C side of forwarded vars presumes the
> value is not `Qunbound`, so I'd be surprised if there isn't some code
> out there which reads such vars and then puts the result somewhere ELisp
> can see it.  E.g. if you `(makunbound 'buffer-file-name)` and then call
> `(buffer-file-name)`.

Fair enough.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-24  5:38         ` Po Lu
@ 2024-05-24 14:10           ` Stefan Monnier
  2024-05-26  1:52             ` Po Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2024-05-24 14:10 UTC (permalink / raw)
  To: Po Lu; +Cc: Stefan Monnier via Emacs development discussions.

>> I'd expect that the connection between the ELisp var and the C var is
>> "forever", especially since once the connection is broken there's no way
>> to re-establish it, so I think it's a drastic effect.
> Uninterning the variable's name would also produce such a "drastic
> effect", at least in code loaded after the fact.

Indeed, uninterning symbols from the global obarray is a really
dangerous operation (which is why we changed `unintern` to make its
second argument non-optional).
But that's not specific to variables-with-forwarding.

> IMHO, the meaning of `makunbound' is to revert the effect of the
> operation that established the binding within the current dynamic scope,
> be that a DEFVAR_LISP or a setq.

I guess that can make sense too.  But I'm not sure what it implies w.r.t
the interaction with a dynbound let-binding (should `makunbound` just
undo the last let-binding?).

> But all these are details, and my only wish is to see this decided one
> way or the other, preferably soon.

I suggest a patch like the one below.


        Stefan


diff --git a/src/data.c b/src/data.c
index be7ae023d8d..18e41dce334 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1743,20 +1742,19 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
 	    set_blv_valcell (blv, tem1);
 	  }
 
-	/* Store the new value in the cons cell.  */
-	set_blv_value (blv, newval);
-
 	if (blv->fwd.fwdptr)
 	  {
 	    if (voide)
-	      /* If storing void (making the symbol void), forward only through
-		 buffer-local indicator, not through Lisp_Objfwd, etc.  */
-	      blv->fwd.fwdptr = NULL;
+	      error ("This variable cannot be void");
 	    else
 	      store_symval_forwarding (blv->fwd, newval,
 				       BUFFERP (where)
 				       ? XBUFFER (where) : current_buffer);
 	  }
+
+	/* Store the new value in the cons cell.  */
+	set_blv_value (blv, newval);
+
 	break;
       }
     case SYMBOL_FORWARDED:
@@ -1780,11 +1778,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
 	  }
 
 	if (voide)
-	  { /* If storing void (making the symbol void), forward only through
-	       buffer-local indicator, not through Lisp_Objfwd, etc.  */
-	    sym->u.s.redirect = SYMBOL_PLAINVAL;
-	    SET_SYMBOL_VAL (sym, newval);
-	  }
+	  error ("This variable cannot be void");
 	else
 	  store_symval_forwarding (/* sym, */ innercontents, newval, buf);
 	break;




^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-24 14:10           ` Stefan Monnier
@ 2024-05-26  1:52             ` Po Lu
  2024-05-26  4:53               ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Po Lu @ 2024-05-26  1:52 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: Stefan Monnier via Emacs development discussions., Eli Zaretskii

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> I suggest a patch like the one below.
>
>
>         Stefan

Fine by me, though I would suggest replacing the word "void" with
"unbound".  Eli?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-26  1:52             ` Po Lu
@ 2024-05-26  4:53               ` Eli Zaretskii
  2024-05-26  5:36                 ` Po Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-05-26  4:53 UTC (permalink / raw)
  To: Po Lu; +Cc: monnier, emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Cc: Stefan Monnier via "Emacs development discussions."
>  <emacs-devel@gnu.org>, Eli Zaretskii <eliz@gnu.org>
> Date: Sun, 26 May 2024 09:52:45 +0800
> 
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
> 
> > I suggest a patch like the one below.
> >
> >
> >         Stefan
> 
> Fine by me, though I would suggest replacing the word "void" with
> "unbound".  Eli?

I don't understand the effect of this, so I cannot make up my mind
about the change.

Do we really need this now, before emacs-30 is cut, or can we wait?
In general, I'd prefer deep low-level changes that affect everything
to be deferred to Emacs 31.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-26  4:53               ` Eli Zaretskii
@ 2024-05-26  5:36                 ` Po Lu
  2024-05-26  6:54                   ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Po Lu @ 2024-05-26  5:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> I don't understand the effect of this, so I cannot make up my mind
> about the change.
>
> Do we really need this now, before emacs-30 is cut, or can we wait?

Whichever you prefer, really.

> In general, I'd prefer deep low-level changes that affect everything
> to be deferred to Emacs 31.

OK.  Is there any ETA on when we might expect the branch to be cut?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Unbinding let-bound built-in variables
  2024-05-26  5:36                 ` Po Lu
@ 2024-05-26  6:54                   ` Eli Zaretskii
  0 siblings, 0 replies; 17+ messages in thread
From: Eli Zaretskii @ 2024-05-26  6:54 UTC (permalink / raw)
  To: Po Lu; +Cc: monnier, emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Cc: monnier@iro.umontreal.ca,  emacs-devel@gnu.org
> Date: Sun, 26 May 2024 13:36:10 +0800
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > In general, I'd prefer deep low-level changes that affect everything
> > to be deferred to Emacs 31.
> 
> OK.  Is there any ETA on when we might expect the branch to be cut?

"Soon".



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2024-05-26  6:54 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <87pltdcaa7.fsf.ref@yahoo.com>
2024-05-23  6:28 ` Unbinding let-bound built-in variables Po Lu
2024-05-23  7:12   ` Eli Zaretskii
2024-05-23  7:31     ` Po Lu
2024-05-23  8:08       ` Eli Zaretskii
2024-05-23  9:13         ` Po Lu
2024-05-23 10:00           ` Eli Zaretskii
2024-05-23 11:18             ` Po Lu
2024-05-23 11:32               ` Eli Zaretskii
2024-05-23 14:47   ` Stefan Monnier via Emacs development discussions.
2024-05-24  1:30     ` Po Lu
2024-05-24  3:35       ` Stefan Monnier
2024-05-24  5:38         ` Po Lu
2024-05-24 14:10           ` Stefan Monnier
2024-05-26  1:52             ` Po Lu
2024-05-26  4:53               ` Eli Zaretskii
2024-05-26  5:36                 ` Po Lu
2024-05-26  6:54                   ` Eli Zaretskii

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