issues with nameref resolution loop in a function

2018-12-08 Thread Grisha Levit
There seems to be an issue with the following new bash-5.0 feature:

  A nameref name resolution loop in a function now resolves to a variable by
  that name in the global scope.

[ Note: "warning: x: circular name reference" messages omitted below. ]

While referencing such a nameref works as described, scalar assignment to it
modifies the variable from the next higher scope rather than the global one:

$ inner() { local -n x=x; x=3; }
$ outer() { local x=2; inner; declare -p x; }
$ x=1; outer; declare -p x
declare -- x="3"# x changed in outer()
declare -- x="1"# global x not changed

There is odd/broken behavior when `declare' is used to modify such a
variable,
similar to https://lists.gnu.org/archive/html/bug-bash/2018-07/msg00072.html
I think the right thing here would be for `declare' to act as if the `-g`
flag
had been supplied and modify the variable in the global scope?

$ f() { local -n x=x; declare x=(2); x=3; declare -p x; }
$ x=1; f; declare -p x
declare -an x=([0]="2") # local nameref borked
declare -- x="1"# global x not changed

$ f() { local -n x=x; declare x=2; }; f
-bash: declare: `2': invalid variable name for name reference

$ f() { local -n x=x; declare -a x=y; declare -p x; }
$ x=1; f; declare -p x
declare -an x=()# local nameref borked
declare -a x=([0]="y")  # global x correct (?)
$ unset x; declare -p x
declare -- x="1"# original after unset

`unset' (no `-n') modifies the nameref:

$ f() { local -n x=x; unset x; declare -p x; }
$ x=1; f; declare -p x
declare -- x
declare -- x="1"

If the target is an array reference that results in a circular nameref,
then
neither referencing nor assigning to the nameref works:

$ f() { local -n x=x[0]; echo "<$x>"; x=2; }
$ x=1; f
<>
-bash: `x[0]': not a valid identifier


Re: temp env allows variables that look like array subscripts

2018-12-08 Thread Grisha Levit
FWIW, namerefs in the temporary environment bypass the implemented checks:

$ declare -n ref=var[0]
$ ref=X printenv 'var[0]'
X


assignment to a nameref that resolves to the temporary environment

2018-12-08 Thread Grisha Levit
When a nameref local to a higher function scope points to a variable in the
temporary environment, that nameref (correctly, it seems) expands to the
value
of the target variable from the temporary environment. However, assignment
to
the nameref modifies the variable from the higher scope, bypassing the
tempenv:

$ a() { local -n ref=var; var=tmp b; echo $ref; }
$ b() { ref=$ref; }
$ var=foo; a
tmp


should `local' create local variables when they exist in the tempenv?

2018-12-08 Thread Grisha Levit
When a variable is present in the temporary environment and then declared
local in a function, it seems to not actually make a local variable, in the
sense that the variable does not show up in the output of `local',
unsetting
the variable reveals the variable from the higher scope rather than marking
it invisible, etc.

$ f() { local v=x; local -p; }; v=t f

$ f() { local v; declare -p v; }; v=t f
declare -x v="t"

$ f() { local v=x; unset v; declare -p v; }; v=g; v=t f
declare -- v="g"

Is this intentional?