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

Re: [BUG & tentative PATCH] Invalid call to upscope in createparam



On Mon, Jun 2, 2025 at 1:56 AM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>
> Here is the test example with comments showing what I think should happen:
>
> bar=xx
> typeset -n foo=bar
> () {
>   typeset -n foo;   # Creates a local "foo" placeholder ref.
>   foo=zz;           # Initializes the local "foo" placeholder ref with "zz" (the name of a not-yet-defined variable).
>   foo=zz || print -u2 foo: assignment failed;   # Creates the global variable "zz" and initializes it with "zz".
>   print $bar $zz;   # Prints the content of the global variable "bar" and "zz", which results in "xx zz".
> }

No.  The "title" of that test is "local nameref may not in-scope a
global parameter" -- a "typeset -n" reference can only refer to an
object that is either already in scope, or that later comes into the
namref's local scope by other means.

> () {
>   typeset -n foo;   # Creates a local "foo" placeholder ref.
>   foo=zz;           # Initializes the local "foo" placeholder ref with a reference to the global "zz" variable.

This should not happen, because unless the previous function has gone
wrong, there is no global zz variable.  The second function is there
to check that the first one did NOT create a global parameter.

>   local zz;         # Creates a local "zz" variable initialized with "".
>   foo=zz;           # Assigns "zz" to the global variable "zz".
>   print $bar $zz;   # Prints the content of the global variable "bar" and the local variable "zz", which results in "xx".
> }

So this is OK and assigns to the global:
() {
  typeset -n ref=gg
  typeset -g gg
  ref=assign1
}

And this is the same:
typeset gg
() {
  typeset -n ref=gg
  typeset gg
  ref=assign2
}

But this must use the local:
() {
  typeset -n ref=gg
  typeset gg
  ref=assign3
}
because at this point the local variable gg exists and no global can
be created "above" it.

This is OK and creates a global, because -u explicitly refers to the
surrounding scope:
() {
  typeset -nu ref=gg
  ref=assign4
}

But this has to fail because the local prevents creation of the global:
() {
  typeset -nu ref=gg
  typeset gg
  ref=assign5
}

Presently "ref=assign5" silently returns $?=1 in that case, but  I
intend to change that.




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