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

Re: A solution to fix hidden references in reference chains



On Mon, Mar 16, 2026 at 6:23 PM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>>
>> scoperefs is a C array of LinkList pointers.  It will always be as
>> large as the greatest locallevel (deepest nested scope) in which a
>> nameref has pointed to a nested parameter
>
> One issue with a list of lists is that it can become expensive to find the list of params of a given scope. In the example below each call to "rec" needs to insert the "r" of the enclosing scope into the list of the current scope. That's cheap as that would be the list at the head of the list of lists. However, the last call to "rec" needs to insert "ref" into the list of the scope of "inner". That's expensive because it's behind the 100 lists corresponding to the 100 scopes of "rec".

So, speed/space tradeoff.  I guess the question would be how often we
need to find a named reference 100 scopes away vs. how often we need
100 scoperefs at all, and whether the never-freed 800 bytes (?) is
worth worrying about.

> Another issue with a list of lists arises in case you only want to store non-null/empty lists. Then you need an additional data structure to tell you to which scope each list of params corresponds to.

Yes, you'd need a structure consisting of a node and a level.

> You can "unset" an enclosing parameter and then redefine/reuse it with "typeset -g".

But you can't change a named reference into something else that way.
Even "unset -n" doesn't remove the nameref-ness of the surrounding
scope parameter.

Aside #1:  Should this code in bin_unset have changed along with other
parts of array-initializer removal in workers/53776?
            if ((pm->node.flags & PM_NAMEREF) &&
                (!(pm = resolve_nameref(pm)) || pm->width)) {
                /* warning? */
                continue;
            }
(That is, pm->width now irrelevant here?)

Aside #2, noting here so I don't have to refresh my memory again:
% typeset -n positional=3

This used to produce
zsh: invalid variable name: 3

but as of workers/54064 this is allowed:
% typeset -p positional
typeset -n positional=3

with an intent to fix later to be a reference to $3 (currently
$positional always returns empty).  Now it only happens for "up"
namerefs:
% () { typeset -nu wrong=5 }
(anon): invalid name reference: 5

This is a bit more interesting now that we can't nameref to argv[3].

> The example below shows how the "ref" parameter defined in "scope1" can be added to the list of params to reset of "scope2" AND of "scope3".

Note to self:  Run some variants of this example after applying workers/54196

> I should probably add some explicit tests for the following cases:
> - Ref added to multiple scope lists
> - Ref added multiple times to the same scope list
> - Ref added to a scope list is now an integer with base=N

Per above, I think this is actually impossible, at least at present?

> - Ref added to a scope list was unset (btw, the code should probably explicitly skip params with PM_UNSET)




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