#4443 upvar-7.1 leaves irremovable variable

obsolete: 8.5.7
open
5
2011-04-12
2009-10-21
No

Here is the test (stolen from tcl/tests/upvar.test):

package require tcltest
tcltest::test upvar-7.1 {upvar to same level} {
set x 44
set y 55
catch {unset uv}
upvar #0 x uv
set uv abc
upvar 0 y uv
set uv xyzzy
list $x $y
} {abc xyzzy}

The test passed. After the test, try these commands:

info globals uv; # returns uv
set uv; # returns "xyzzy"
unset uv; # appears to succeed.
info globals uv; # still returns uv
unset uv; # fails with error: 'can't unset "uv": no such variable'

Discussion

  • Joe Mistachkin

    Joe Mistachkin - 2009-10-21

    This bug also applies to 8.4 and HEAD.

     
  • Alexandre Ferrieux

    Minimal repro without tcltest, and with a single toplevel upvar:

    % upvar 0 x uv
    % set uv 34
    34
    % unset uv
    % info globals uv
    uv
    % info globals x
    %

     
  • Joe Mistachkin

    Joe Mistachkin - 2009-10-21

    Test upvar-8.10 also leaves an irremovable variable upvarArrayElemAlias.

     
  • Alexandre Ferrieux

    Hum, I fear all this is documented. Fom upvar.n:
    " If an upvar variable is unset [...], the unset operation affects the variable
    " it is linked to, not the upvar variable. There is no way to unset an upvar
    " variable except by exiting the procedure in which it is defined.

    Of course the "procedure in which it is defined" here is toplevel, so it looks like there simply isn't the necessary machinery to clean that leak up.
    Unsure whether there's a real motivation to do so, since toplevel code is hardly a constraint in production... Tempted to say something between "Invalid" and "Won't fix" :-}

     
  • Joe Mistachkin

    Joe Mistachkin - 2009-10-21

    At a minimum, the docs should include a special mention of non-proc scopes (global, ns, etc) that indicates that variable cannot be removed at all. Additionally, should these zombie variables really show up in [info globals] and/or [info vars]?

     
  • Alexandre Ferrieux

    I agree that clarifying the docs is a no-brainer. Now, looking at the code, I don't see a compelling reason why it should be hard to remove a linkvar. Possibly it is just the lack of script-level API to do so ? In that case, a TIP could resolve the issue in a more constructive way than writing the sad truth in the docs. For example, a second [unset] (the first one removeing the linked-to var) cound remove the link. Or an option to [unset]: [unset -link].

    Miguel, am I missing something ? Would the fabric of spacetime collapse if we allowed to remove a linkvar ? Or do you think there are too few real use cases ?

     
  • Jan Nijtmans

    Jan Nijtmans - 2009-10-21

    The same happens when using namespace variables:

    % namespace eval x {upvar 0 x uv;set uv 34}
    34
    % set x::x
    34
    % unset x::x
    % set x::uv
    can't read "x::uv": no such variable
    % namespace eval x {info vars uv}
    uv

    Giving it some thoughts, upvar is really only
    meant to be used for local variables. What
    would happen if we changed the documentation
    and the implementation: In case the linkvar is
    a global or a namespace variable, then an
    unset should just remove both. Would any
    test case fail if this was changed? It's
    worth a try, but I guess that it wouldn't
    bother any practical case.

    Yes, a TIP is needed for this. Is there
    anyone out there who has a counter
    example of a use case where this
    change would be a problem? If not,
    then I would suggest to change the
    behavior and the implementation.

     
  • Donal K. Fellows

    A [variable] command can have the same effect, and did so at least as far back as 8.4:
    % namespace eval xy {variable uv}
    % info vars xy::*
    ::xy::uv
    (All this really means is that using [info exists] isn't redundant, and maybe we need to document more carefully.)

    More worrying is that setting a trace on a non-existent variable does not put it into the same odd state.

     
  • Donal K. Fellows

    Plus you can delete non-local upvar aliases by deleting the namespace concerned (for the global ns, this means nuking the interpreter).

     
  • Don Porter

    Don Porter - 2009-10-21

    Just an aside:

    actually [namespace delete ::] falls just
    short of "nuking the interp". For example,
    hidden commands survive.

     
  • Donal K. Fellows

    yeah, but the effect for scripts is very similar...

     
  • miguel sofer

    miguel sofer - 2011-04-12
    • assigned_to: msofer --> mistachkin
     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks