zsh-users
 help / color / mirror / code / Atom feed
* unset private variables
@ 2023-09-03 12:06 jsks
  2023-09-03 18:02 ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: jsks @ 2023-09-03 12:06 UTC (permalink / raw)
  To: zsh-users; +Cc: Joshua Krusell

[-- Attachment #1: Type: text/plain, Size: 486 bytes --]

Hi,

Apologizes if I missed something in the documentation, but I'm running into
the following problem and wondering what is the intended behaviour.

Unsetting a variable declared with param/private and then modifying it
returns the error "can't change parameter attribute". Declaring using
`local` works, however, and preserves the `local-scalar` attribute.

Example code, run on zsh-5.9:

zmodload zsh/param/private
function foo() {
    private x=1
    unset x
    x=2
}
foo

/Joshua

[-- Attachment #2: Type: text/html, Size: 700 bytes --]

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

* Re: unset private variables
  2023-09-03 12:06 unset private variables jsks
@ 2023-09-03 18:02 ` Bart Schaefer
  2023-09-03 18:12   ` Bart Schaefer
  0 siblings, 1 reply; 3+ messages in thread
From: Bart Schaefer @ 2023-09-03 18:02 UTC (permalink / raw)
  To: Joshua Krusell; +Cc: zsh-users

[-- Attachment #1: Type: text/plain, Size: 362 bytes --]

On Sun, Sep 3, 2023 at 5:06 AM jsks <js.shirin@gmail.com> wrote:
>
> Unsetting a variable declared with param/private and then modifying it returns the error "can't change parameter attribute".

This is a bug, an unintended interaction with with changes introduced
for the TYPESET_TO_UNSET option (but not affected by whether that
option is in effect).

[-- Attachment #2: unset-private.txt --]
[-- Type: text/plain, Size: 3079 bytes --]

diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c
index e43f0edb4..8e04b2b95 100644
--- a/Src/Modules/param_private.c
+++ b/Src/Modules/param_private.c
@@ -230,7 +230,9 @@ setfn_error(Param pm)
  * calling the original unsetfn.  This assures that if the old unsetfn
  * wants to use its getfn or setfn, they're unconditionally present.
  * The "explicit" flag indicates that "unset" was called, if zero the
- * parameter is going out of scope (see params.c).
+ * parameter is going out of scope (see params.c).  PM_DECLARED is
+ * asserted as if TYPESET_TO_UNSET were in use so that the private
+ * parameter is re-used rather than re-created when assigned again.
  *
  */
 
@@ -268,9 +270,10 @@ pps_unsetfn(Param pm, int explicit)
     pm->gsu.s = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.s = (GsuScalar)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -307,9 +310,10 @@ ppi_unsetfn(Param pm, int explicit)
     pm->gsu.i = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.i = (GsuInteger)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -346,9 +350,10 @@ ppf_unsetfn(Param pm, int explicit)
     pm->gsu.f = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.f = (GsuFloat)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -386,9 +391,10 @@ ppa_unsetfn(Param pm, int explicit)
     pm->gsu.a = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.a = (GsuArray)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
@@ -427,9 +433,10 @@ pph_unsetfn(Param pm, int explicit)
     pm->gsu.h = gsu;
     if (locallevel <= pm->level)
 	gsu->unsetfn(pm, explicit);
-    if (explicit)
+    if (explicit) {
+	pm->node.flags |= PM_DECLARED;
 	pm->gsu.h = (GsuHash)c;
-    else
+    } else
 	zfree(c, sizeof(struct gsu_closure));
 }
 
diff --git a/Src/builtin.c b/Src/builtin.c
index 31af66c7c..01df7d73b 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2697,7 +2697,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
 	    off |= bit;
     }
     if (OPT_MINUS(ops,'n')) {
-	if ((on|off) & ~PM_READONLY) {
+	if ((on|off) & ~(PM_READONLY|PM_HIDEVAL)) {
 	    zwarnnam(name, "no other attributes allowed with -n");
 	    return 1;
 	}
diff --git a/Test/V10private.ztst b/Test/V10private.ztst
index b191afcb7..b876f548d 100644
--- a/Test/V10private.ztst
+++ b/Test/V10private.ztst
@@ -377,6 +377,13 @@ F:Should we allow "public" namerefs to private parameters?
 *?*no such variable: ptr1
 *?*no such variable: ptr2
 
+ () {
+   private x=1
+   unset x
+   x=2
+ }
+0:regression test for unset private
+
 %clean
 
   rm -r private.TMP

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

* Re: unset private variables
  2023-09-03 18:02 ` Bart Schaefer
@ 2023-09-03 18:12   ` Bart Schaefer
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 2023-09-03 18:12 UTC (permalink / raw)
  To: Joshua Krusell; +Cc: zsh-users

On Sun, Sep 3, 2023 at 11:02 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> This is a bug, an unintended interaction with with changes introduced
> for the TYPESET_TO_UNSET option (but not affected by whether that
> option is in effect).

Oops, ignore the builtin.c change in that patch, it leaked in from
some unrelated testing.


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

end of thread, other threads:[~2023-09-03 18:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-03 12:06 unset private variables jsks
2023-09-03 18:02 ` Bart Schaefer
2023-09-03 18:12   ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

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 NNTP newsgroup(s).