Tcl Source Code

View Ticket
Login
Ticket UUID: 231259
Title: shadowing byte-compiled commands
Type: Bug Version: obsolete: 8.4a3
Submitter: msofer Created on: 2001-02-06 14:43:08
Subsystem: 21. [namespace] Assigned To: msofer
Priority: 3 Low Severity:
Status: Closed Last Modified: 2001-11-30 03:10:39
Resolution: Fixed Closed By: msofer
    Closed on: 2001-11-29 20:10:39
Description:
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
User Comments: msofer added on 2001-11-30 03:10:39:
Logged In: YES 
user_id=148712

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

msofer added on 2001-11-29 21:42:49:
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.

msofer added on 2001-05-15 21:23:13:
Logged In: YES 
user_id=148712

Patch committed

msofer added on 2001-05-11 05:54:42:

File Added - 6189: 231259.txt

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?

msofer added on 2001-05-11 03:50:33:
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 ...

msofer added on 2001-05-11 02:14:21:
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

msofer added on 2001-02-08 04:16:51:
No, I'm not ...

msofer added on 2001-02-08 03:25:51:
I am submitting a patch to tclProc.c that fixes this.

msofer added on 2001-02-08 01:35:19:
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.

msofer added on 2001-02-06 23:06:27:
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

Attachments: