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

Re: Bogus self reference error with -nu



I don't think that the example should trigger any error or warning. Both, ref1 and ref2 refer to not-yet-defined variables. It happens that the function contains a local variable that would prevent the creation of the global variable referred to by "ref2" but that problem should only ever be signaled if one tries to assign something to "ref2". The function could later define a local variable "foo". At that point creating the global variable referred to by "ref1" would also become impossible but surely we won't signal that when the local "foo" is defined (nor would it be signaled if "foo" was defined before "ref1" is initialized with "foo").

Philippe


On Sat, May 31, 2025 at 9:17 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
On Wed, May 21, 2025 at 1:03 AM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>
> function () {
>   typeset -nu ref1=foo
>   echo ref1=$ref1
>   typeset -nu ref2=ref2
>   echo ref2=$ref2
> }
>
> There is no ref2 in the upper scope, so there should be no self reference error.

It took more head-scratching for this than it should have, but there
is in fact a reference error here -- it's just that the error message
could stand to be clarified.

The problem here is that "local -nu ref2=ref2" creates a reference not
just to a global that doesn't exist, but to a global that CAN NEVER
exist, because the local is in the way.  The following changes the
error message.  (I'll include it in a larger patch as an attachment
later.)

diff --git a/Src/params.c b/Src/params.c
index 7b515515e..2f4658f7a 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -6436,7 +6436,10 @@ setscope(Param pm)
        }
        if (refname && upscope(pm, pm->base) == pm &&
            strcmp(pm->node.nam, refname) == 0) {
-           zerr("%s: invalid self reference", refname);
+           if (pm->node.flags & PM_UPPER)
+               zerr("%s: local reference hides nonexistent global", refname);
+           else
+               zerr("%s: invalid self reference", refname);
            unsetparam_pm(pm, 0, 1);
        }
     } while (0);

This will have to be reconciled with Philippe's upscope_upper() patch,
which may have some merit, but at this point the patch relies on
upscope() not caring about upper.

> Once that bug is fixed, it's worth testing the following where the two references should again behave the same.
>
> function () {
>   typeset -nu ref1=foo
>   typeset foo=init
>   ref1=assign
>   echo ref1=$ref1
>   typeset -nu ref2=ref2
>   ref2=assign
>   echo ref2=$ref2
> }
> typeset -p foo ref2

They do behave the same post-patch in that both produce the "hides
nonexistent" error.



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