issues with nameref resolution loop in a function
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
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
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?
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?