Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: hiding of specials and namerefs



On Sun, Jul 19, 2026 at 1:34 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
>
> -- `typeset -hn ...` is not allowed, but can be worked around, so
> probably should be allowed?
> -- the ZLE parameters are already implicitly local on entry to a
> widget function, so declaring them local again (even with -h) doesn't
> change anything without introducing another scope.

Attached patch addresses these.

On Wed, Jul 22, 2026 at 4:42 PM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>
> [Regarding the second point above]
>
> I assume that -h is a rather rarely used flag. It's probably even more rarely used in cases where it fails to hide the targeted parameter. So, while an error changes the behavior, there are probably extremely few existing scripts where this would make a difference. On the other hand, while you develop a new script, an error is somewhat more likely to grab your attention.

The patch makes this an error, and therefore I've updated the tests
after applying workers/55024 (pushed but not yet in ChangeLog).

I put the related code in an #if to make it easy to try either variation.

On Thu, Jul 23, 2026 at 7:12 PM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>>
>> % typeset -gn SRANDOM
>> zsh: invalid variable name: zsh/random
>
> I have code that fixes this  -> changes the error to "SRANDOM: can't change type of autoloaded parameter".

Given that mention, I've stopped short of digging into this myself,
this patch does not cover it.
diff --git a/Src/builtin.c b/Src/builtin.c
index 2e3e5752a..79a7678ab 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2209,6 +2209,17 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	    on |= PM_EXPORTED;
 	*/
     }
+    if (usepm && (on & PM_HIDE) &&
+	(pm->node.flags & (PM_SPECIAL|PM_AUTOLOAD)) &&
+	pm->level <= locallevel) {
+#if 0
+	zwarnnam(cname, "%s: can't change parameter attribute", pname);
+	/* return NULL; */	/* this has always been a no-op */
+#else
+	zerrnam(cname, "%s: can't change parameter attribute", pname);
+	return NULL;	/* this was previously a no-op */
+#endif
+    }
 
     /*
      * A parameter will be local if
@@ -2516,8 +2527,8 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	pm = createparam(pname, on & ~PM_READONLY);
 	if (!pm) {
 	    if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z |
-		      PM_INTEGER | PM_EFLOAT | PM_FFLOAT))
-		zerrnam(cname, "can't change variable attribute: %s", pname);
+		      PM_INTEGER | PM_EFLOAT | PM_FFLOAT | PM_NAMEREF))
+		zerrnam(cname, "%s: can't change parameter attribute", pname);
 	    return NULL;
 	}
 	if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
@@ -2689,14 +2700,14 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
 	else
 	    continue;
 	if (OPT_MINUS(ops,'n')) {
-	    if (bit & ~(PM_READONLY|PM_UPPER|PM_HIDEVAL)) {
+	    if (bit & ~(PM_READONLY|PM_UPPER|PM_HIDEVAL|PM_HIDE)) {
 		zwarnnam(name, "-%c not allowed with -n", optval);
 		/* return 1; */
 	    }
 	}
     }
     if (OPT_MINUS(ops,'n')) {
-	if ((on|off) & ~(PM_READONLY|PM_UPPER|PM_HIDEVAL)) {
+	if ((on|off) & ~(PM_READONLY|PM_UPPER|PM_HIDEVAL|PM_HIDE)) {
 	    /* zwarnnam(name, "no other attributes allowed with -n"); */
 	    return 1;
 	}
diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst
index fe9eb55eb..b45ad027f 100644
--- a/Test/B02typeset.ztst
+++ b/Test/B02typeset.ztst
@@ -1133,9 +1133,9 @@
  echo v=${SRANDOM/<->/integer}
  typeset -gh SRANDOM
  echo v=${SRANDOM/<->/integer}
-0:Global -h variable doesn't hide special variable
->v=integer
+1:Global -h variable doesn't hide special variable
 >v=integer
+?(eval):typeset:3: SRANDOM: can't change parameter attribute
 
  zmodload -u zsh/random
  echo v=${SRANDOM/<->/integer}
@@ -1168,10 +1168,9 @@
  typeset -gh SRANDOM
  echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
  echo v=${SRANDOM/<->/integer}
-0:Global -h variable doesn't hide autoload variable
->z=SRANDOM (zsh/random)
+1:Global -h variable doesn't hide autoload variable
 >z=SRANDOM (zsh/random)
->v=integer
+?(eval):typeset:3: SRANDOM: can't change parameter attribute
 
  zmodload -u zsh/random
  echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}


Messages sorted by: Reverse Date, Date, Thread, Author