Flush PL_stashcache when assigning a file handle to a typeglob.
authorNicholas Clark <nick@ccl4.org>
Sun, 23 Sep 2012 20:48:42 +0000 (22:48 +0200)
committerNicholas Clark <nick@ccl4.org>
Wed, 26 Sep 2012 21:28:50 +0000 (23:28 +0200)
File handles take priority over stashes for method dispatch. Assigning a
file handle to a typeglob potentially creates a file handle where one did
not exist before. As PL_stashcache only contains entries for names which
unambiguously resolve to stashes, such a change may mean that PL_stashcache
now contains an invalid entry. As it's hard to work out exactly which entries
might be affected, simply flush the entire cache and let it rebuild itself.

sv.c
t/op/method.t

diff --git a/sv.c b/sv.c
index bd8afb7..2417e86 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3883,6 +3883,14 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
            assert(mg);
            Perl_magic_clearisa(aTHX_ NULL, mg);
        }
+        else if (stype == SVt_PVIO) {
+            DEBUG_o(Perl_deb(aTHX_ "glob_assign_ref clearing PL_stashcache\n"));
+            /* It's a cache. It will rebuild itself quite happily.
+               It's a lot of effort to work out exactly which key (or keys)
+               might be invalidated by the creation of the this file handle.
+            */
+            hv_clear(PL_stashcache);
+        }
        break;
     }
     SvREFCNT_dec(dref);
index 29cb82b..5ed8f76 100644 (file)
@@ -581,14 +581,11 @@ SKIP: {
     *Color::H1 = *Colour::H1{IO};
 
     is(Colour::H1->getline(), <DATA>, 'read from a file');
-    { local $::TODO = "regression introduced when PL_stashcache was first added";
     is(Color::H1->getline(), <DATA>,
        'file handles take priority after typeglob assignment');
-    }
 
     *Color::H1 = *CLOSED{IO};
     {
-       local $::TODO = "regression introduced when PL_stashcache was first added";
        no warnings 'io';
        is(Color::H1->getline(), undef,
           "assigning a closed a file handle doesn't change object resolution");