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

Undetected self references



> () {
>   typeset -n ref1=ref2
>   typeset -n ref2
>   () {
>     () {
>       typeset ref1=inner;
>       ref2=ref1
>       echo "ref1=$ref1 ref2=$ref2"
>     }
>     echo "ref1=$ref1 ref2=$ref2"
>   }
> }

That's not a loop either.  The very first ref1=ref2 creates a
reference to a nonexistent but otherwise non-reference global ref2,
and by the end you have a chain ref2 to ref1 to nothing, even though
you can't see it unless you actually instantiate a (normal scalar)
ref2 in global scope.  I admit it's a pretty weird case.

I think you overlook something or there is something fundamental that I don't understand. Here is an updated version where I added function names and an assignement to ref1 (assigning to ref2 produces the same result).

f1 () {
  typeset -n ref1=ref2
  typeset -n ref2
  f2 () {
    f3 () {
      typeset ref1=inner;
      ref2=ref1
      echo "$0: ref1=$ref1 ref2=$ref2"
    }
    f3
    echo "$0: ref1=$ref1 ref2=$ref2"
    ref1=foo
  }
  f2
}
f1


Output:
f3: ref1=inner ref2=inner
f2: ref1=ref1 ref2=ref2
f2:8: foo: invalid self reference

The second line looks already suspiciously wrong to me. The third line (triggered by "ref1=foo") indicates that there is indeed a circular chain of references.

The chain is created when "f3" is exited. You could detect it when you update the "base" field of "ref2". To do so, you would have to lookup what "ref2" refers to in "f2".



Here is an updated version of the example for loose references:

f1 () {
  typeset ref1=outer
  f2 () {
    typeset -n ref2=ref1
    echo "ref1=$ref1 ref2=$ref2"
    typeset -n ref1=ref2
    echo "ref1=$ref1 ref2=$ref2"
    ref1=foo
  }
  f2
}
f1

Output (from zsh-loose):
ref1=outer ref2=outer
ref1=ref1 ref2=ref2
f2:5: foo: invalid self reference

The output is exatcly the same as for the first example but here I'm surprised that the loop isn't detected when "typeset -n ref1=ref2". If I comment out "typeset ref1=outer", then the loop is indeed detect at that point of time:

ref1= ref2=
f2:typeset:3: ref1: invalid self reference
ref1= ref2=

No need to investiagate that since my "zsh-loose" patch is just a hack. I'm just surprised that "typeset -n ref1=ref2" somehow fails to see the loop but it's most likely due because in my patch "setscope" still relies on the "base" field and on the old "upscope" function.



Below is the first test in K01nameref.ztst that triggers a "math recursion limit exceeded" with zsh-loose:

typeset -A var=(myself outside)
() {
  typeset -n myself=var[myself]
  local -h var
  print -r -- $myself
  typeset -p var
}

I see nothing surprising here. With loose references, that code is equivalent to the following one:

() {
  typeset -n myself=var[myself]
  local -h var
  print -r -- $myself
  typeset -p var
}

This code triggers the same "math recursion limit exceeded" with both zsh-loose and the current implementation.

The same happens for the second example with "myself".

Philippe



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