This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Make SUPER::method respect method changes in moved pkg
authorFather Chrysostomos <sprout@cpan.org>
Fri, 14 Sep 2012 21:20:07 +0000 (14:20 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 15 Sep 2012 05:29:47 +0000 (22:29 -0700)
->SUPER::method calls inside the Foo package cache the method for
reuse inside the stash Foo::SUPER.

Before the call, @Foo::SUPER::ISA is set to "Foo", so that those
caches will be invalidated properly.  (@ISA has the magic to make that
work.)  The actual value in @Foo::SUPER::ISA unused.

Now we have two types of package names.  If you alias the Foo package
and then clobber the original entry:

    *Bar:: = *Foo::;
    undef *Foo::;

__PACKAGE__ and HvNAME will return Foo still, but HvENAME (the effec-
tive name) will return Bar, because that is where the package is to be
found.

As of the previous commit, the package used for ISA is based on the
effective name, Bar::SUPER in this case.

But @Bar::SUPER::ISA is still set to Foo.  So even if we make changes
to methods inherited by what is now the Bar package, a previous method
cached in *Bar::SUPER::method will be reused.

BEGIN {
    *Bar:: = *Foo::;
    undef *Foo::;
}
package Bar;
@ISA = 'Baz';
*Baz::m = sub { "method 1" };
anthying->SUPER::m;
undef *Baz::m;
*Baz::m = sub { "method 2" };
warn anything->SUPER::m;
__END__
method 1 at - line 11.

gv.c
t/op/method.t

diff --git a/gv.c b/gv.c
index 6b6e493..e64c8f2 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -921,7 +921,7 @@ S_gv_get_super_pkg(pTHX_ const char* name, I32 namelen, U32 flags)
     GvMULTI_on(gv);
     sv_magic(MUTABLE_SV(superisa), MUTABLE_SV(gv), PERL_MAGIC_isa, NULL, 0);
     av_push(superisa, newSVhek(CopSTASH(PL_curcop)
-                              ? HvNAME_HEK(CopSTASH(PL_curcop)) : NULL));
+                              ? HvENAME_HEK(CopSTASH(PL_curcop)) : NULL));
 
     return stash;
 }
index aaa70be..584ffd9 100644 (file)
@@ -13,7 +13,7 @@ BEGIN {
 use strict;
 no warnings 'once';
 
-plan(tests => 109);
+plan(tests => 110);
 
 @A::ISA = 'B';
 @B::ISA = 'C';
@@ -262,6 +262,10 @@ sub OtherSouper::method { "Isidore Ropen, Draft Manager" }
     sub door::dohtem { 'dohtem' }
     ::is eval { Mover->SUPER::dohtem; }, 'dohtem',
         'SUPER inside moved package';
+    undef *door::dohtem;
+    *door::dohtem = sub { 'method' };
+    ::is eval { Mover->SUPER::dohtem; }, 'method',
+        'SUPER inside moved package respects method changes';
 }
 
 # failed method call or UNIVERSAL::can() should not autovivify packages