This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #79024] Bleadperl 80ebaca breaks OVID/Class-Trait-0.31.tar.gz
authorFather Chrysostomos <sprout@cpan.org>
Thu, 11 Nov 2010 14:12:00 +0000 (06:12 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 11 Nov 2010 17:35:19 +0000 (09:35 -0800)
Commit 80ebaca actually exposed an existing bug that Class::Trait was
really close to triggering already:

  undef *ISA; # @ISA no longer magical

Class::Trait’s tests just happened not to call ->isa before making any
changes to @ISA.

Now that the meta->isa cache is created immediately,
Class::Trait fails.

This bug can be reproduced in earlier perls by putting an ->isa call
right after the undef:

  undef *{"Extra::TSpouse::ISA"};
 'Extra::TSpouse'->isa('Class::Trait::Base');
  unshift @{"Extra::TSpouse::ISA"}, Class::Trait::Base;
  warn Extra::TSpouse->isa('Class::Trait::Base'); # something's wrong

This commit modifies gv_fetchpvn_flags to magicalise @ISA whenever it
is fetched.

gv.c
t/mro/basic.t

diff --git a/gv.c b/gv.c
index 32b5908..5a5a851 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -1219,6 +1219,10 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
                else if (*name == '-' || *name == '+')
                    require_tie_mod(gv, name, newSVpvs("Tie::Hash::NamedCapture"), "TIEHASH", 0);
            }
+           else if (len == 3 && sv_type == SVt_PVAV
+                 && strnEQ(name, "ISA", 3)
+                 && (!GvAV(gv) || !SvSMAGICAL(GvAV(gv))))
+               gv_magicalize_isa(gv);
        }
        return gv;
     } else if (no_init) {
index 353352b..1ecfd21 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-BEGIN { require q(./test.pl); } plan(tests => 49);
+BEGIN { require q(./test.pl); } plan(tests => 50);
 
 require mro;
 
@@ -300,3 +300,15 @@ is(eval { MRO_N->testfunc() }, 123);
     main->do;
     is $output, 'parentparent2', '@main::ISA is magical';
 }
+
+{
+    # Undefining *ISA, then modifying @ISA
+    # This broke Class::Trait. See [perl #79024].
+    {package Class::Trait::Base}
+    no strict 'refs';
+    undef   *{"Extra::TSpouse::ISA"};
+    'Extra::TSpouse'->isa('Class::Trait::Base'); # cache the mro
+    unshift @{"Extra::TSpouse::ISA"}, 'Class::Trait::Base';
+    ok 'Extra::TSpouse'->isa('Class::Trait::Base'),
+     'a isa b after undef *a::ISA and @a::ISA modification';
+}