SourceForge has been redesigned. Learn more.
Close

#1428 shadowing byte-compiled commands

obsolete: 8.4a3
closed-fixed
3
2001-05-15
2001-02-06
No

According to the comments for the function TclResetShadowedCmdRefs in generic/tclNamesp.c the following should not happen:

% #define a namespace proc that uses the global command 'set'
% namespace eval mig {proc test {} {set ::g 0}}; mig::test
0
%
% #define a namespace proc 'set' that shadows the global command;
% #the previously compiled 'test' never notices!
% namespace eval mig {proc set {a b} {::set a [incr b]}}; mig::test 0
% #>>>>>>>>>>>
% #? Shouldn't the namespace epoch have been bumped up by the
% #shadowing, ? so that all procs are recompiled?
% #>>>>>>>>>>>
%
% #if I redefine, and hence force recompilation of 'test', it is ok.)
% namespace eval mig {proc test {} {set ::g 0}}; mig::test
1

Discussion

  • miguel sofer

    miguel sofer - 2001-02-06

    Sorry for the title, it is way too specific and maybe misleading! A correct title would be
    * Incorrect command scoping *

    I do not actually know if, in the example above, cmdRefEpoch was not updated, or if it was but the bytecompiler ignored it.

    msofer

     
  • miguel sofer

    miguel sofer - 2001-02-07

    It seems to be a deeper bug; some global commands (eg, set) are compiled directly to bytecode. Commands that shadow *them* are immune to the implementation of the 'reset on shadowing': it invalidates command *references* in the bytecode, but there is no command reference to 'set' in there!
    Maybe shadowing should force recompilation of the proc, and not just a fresh resolution of command names? In that case, a small patch to TclProcCompileProc (generic/tclProc.c) would arrange it.

     
  • miguel sofer

    miguel sofer - 2001-02-07

    I am submitting a patch to tclProc.c that fixes this.

     
  • miguel sofer

    miguel sofer - 2001-02-07

    No, I'm not ...

     
  • miguel sofer

    miguel sofer - 2001-04-07
    • priority: 5 --> 3
     
  • miguel sofer

    miguel sofer - 2001-04-07
    • assigned_to: nobody --> msofer
     
  • miguel sofer

    miguel sofer - 2001-05-10

    Logged In: YES
    user_id=148712

    A different aspect of the same bug is shown by the example:

    % namespace export set
    namespace eval mig {
    namespace import ::set
    rename set mySet

    proc test {a} {
    variable var
    mySet var $a
    }

    test 0
    set var0 $var

    rename mySet {}
    proc mySet {var val} {
    set $var [expr $val + 1]
    }

    test 0
    set var1 $var

    puts "$var0 $var1"
    }
    % 0 0

     
  • miguel sofer

    miguel sofer - 2001-05-10

    Logged In: YES
    user_id=148712

    Sorry about that "second example"; it is only an example of
    how stupid one gets when doing things in haste ...

    No bug in that situation if programmed correctly: the
    redefinition of 'mySet' should have a body
    {uplevel set $var [expr $val + 1]}
    and then things work out as they should ...

     
  • miguel sofer

    miguel sofer - 2001-05-10
    • milestone: 102439 --> obsolete: 8.4a3
    • summary: cmdRefEpoch not updated --> shadowing byte-compiled commands
     
  • miguel sofer

    miguel sofer - 2001-05-10

    Logged In: YES
    user_id=148712

    I enclose a patch for review. Only issue I see: the usage of
    the
    nsPtr->resolverEpoch
    to force recompilation in the namespace. Maybe we should
    change the name to
    nsPtr->compileEpoch
    throughout?

     
  • miguel sofer

    miguel sofer - 2001-05-10

    patch

     
  • miguel sofer

    miguel sofer - 2001-05-15

    Logged In: YES
    user_id=148712

    Patch committed

     
  • miguel sofer

    miguel sofer - 2001-05-15
    • status: open --> closed-fixed
     
  • miguel sofer

    miguel sofer - 2001-11-29

    Logged In: YES
    user_id=148712

    A simpler example (will go into the tests) is:

    namespace eval test {variable b 0}

    proc test::a {i} {
    variable b
    proc set args {return "New proc is called"}
    return [set b $i]
    }

    list [test::a 1] [test::a 2] $test::b

    The correct output is

    1 {New proc is called} 1

    and the output without the patch is

    1 2 2

    Explanation:

    - at the first run of test::a [::set] is called as it was
    compiled into the proc body. We cannot see the effects of a
    redefinition of a bcc'ed command from within the bytecode
    that did the redefinition, as it will run to the end once it
    starts executing.

    - at successive runs, the shadowed command is detected and
    a recompilation is forced: the new definition is used.

     
  • miguel sofer

    miguel sofer - 2001-11-29

    Logged In: YES
    user_id=148712

    Patch back-ported to the core-8-3-1-branch