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

Re: PATCH: Rebound references don't behave like newly bound ones



Here is an updated version based on workers/54262.

Fix rebound refs to behave the same as newly bound ones.

Philippe


On Sat, Nov 8, 2025 at 4:55 PM Philippe Altherr <philippe.altherr@xxxxxxxxx> wrote:
Two references referencing the same variable should always behave the same. This is currently not always the case if one of them previously referenced a different variable that went out of scope.

Example

typeset -n ref1 ref2

local var=l1

() {

  () {

    local var=l3

    ref1=var

    echo A1: ref1=$ref1 ref2=$ref2

  }

  ref2=var

  # At this point, "ref1" and "ref2" refer to the same variable

  # "var". Going forward, they should behave the same.

  echo A2: ref1=$ref1 ref2=$ref2

  () {

    local var=l3

    echo A3: ref1=$ref1 ref2=$ref2

  }

  echo A4: ref1=$ref1 ref2=$ref2

  local var=l2

  echo A5: ref1=$ref1 ref2=$ref2

}

echo A6: ref1=$ref1 ref2=$ref2


Current output

Expected output

A1: ref1=l3 ref2=

A2: ref1=l1 ref2=l1

A3: ref1=l3 ref2=l1

A4: ref1=l1 ref2=l1

A5: ref1=l2 ref2=l1

A6: ref1=l1 ref2=l1

A1: ref1=l3 ref2=

A2: ref1=l1 ref2=l1

A3: ref1=l1 ref2=l1

A4: ref1=l1 ref2=l1

A5: ref1=l1 ref2=l1

A6: ref1=l1 ref2=l1


Fixing this discrepancy requires adopting what was described as the "all the way up" strategy for rebound variables. Thankfully, once the fix for hidden references is in (workers/54047), implementing "all the way up" is trivial:

diff --git a/Src/params.c b/Src/params.c

index 5e9387339..c737bf748 100644

--- a/Src/params.c

+++ b/Src/params.c

@@ -5853,7 +5853,8 @@ endparamscope(void)

     for (Param pm; refs && (pm = (Param)getlinknode(refs));) {

  if ((pm->node.flags & PM_NAMEREF) && !(pm->node.flags & PM_UPPER) &&

      pm->base > locallevel) {

-     setscope_base(pm, locallevel);

+     pm->base = 0;

+     setscope(pm);

  }

     }

     unqueue_signals();


This change also has for effect to detect and signal incidental reference loops (i.e., reference loops created when a reference is rebound) as soon as the loop is created rather than only when it's first accessed.

Example

typeset -n ref1

typeset -n ref2=ref1;

() {

  typeset ref2=foo

  ref1=ref2

  echo ref1=$ref1

}

echo ref1 and ref2 now form a loop

: $ref1

echo NOT REACHED


Current output

New output

ref1=foo

ref1 and ref2 now form a loop

zsh: ref1: invalid self reference

ref1=foo

zsh: ref2: invalid self reference


Fix rebound refs to behave the same as newly bound ones.

Philippe




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