diff options
author | Father Chrysostomos <sprout@cpan.org> | 2010-11-11 20:29:31 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-11-11 20:32:28 -0800 |
commit | b89cdb229b520dceadf180df9462c8a0a1edf975 (patch) | |
tree | 8a0be1856770d067e6569f7247f2c484bbec70a0 /t/mro | |
parent | eda19b455e8d9bb196ce7fa823d633ff077b2390 (diff) | |
download | perl-b89cdb229b520dceadf180df9462c8a0a1edf975.tar.gz |
Fix package assignment with nested aliased packages
This commit fixes package assignments like *foo:: = *bar:: when both
foo and bar contain nested stashes that are aliases of each other.
mro_package_moved (actually, its auxiliary routine) need to keep a
list of stashes that have been seen as a separate list from those that
are going to have mro_isa_changed_in called on them. Otherwise, some
stashes will simply not be iterated through.
See the test that this adds and its comments. @ISA = @ISA should never
have any effect visible to Perl (with a capital), but it does in that
test case, prior to this commit.
This also fixes another bug that the test case triggered:
riter was not being reset before the second iteration in
mro_gather_and_rename.
Also, the stashes HV (aka the ‘big list’) now holds refcounts on its
elements, as that makes the code simpler as a result of the changes.
Diffstat (limited to 't/mro')
-rw-r--r-- | t/mro/package_aliases.t | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/t/mro/package_aliases.t b/t/mro/package_aliases.t index b4ef2027fe..f2c5c3944f 100644 --- a/t/mro/package_aliases.t +++ b/t/mro/package_aliases.t @@ -10,7 +10,7 @@ BEGIN { use strict; use warnings; -plan(tests => 19); +plan(tests => 20); { package New; @@ -236,6 +236,34 @@ fresh_perl_is { stderr => 1 }, "Assigning a nameless package over one w/subclasses updates isa caches"; +# mro_package_moved needs to make a distinction between replaced and +# assigned stashes when keeping track of what it has seen so far. +no warnings; { + no strict 'refs'; + + sub bar::blonk::blonk::phoo { "bbb" } + sub veclum::phoo { "lasrevinu" } + @feedlebomp::ISA = qw 'phoo::blonk::blonk veclum'; + *phoo::baz:: = *bar::blonk::; # now bar::blonk:: is on both sides + *phoo:: = *bar::; # here bar::blonk:: is both deleted and added + *bar:: = *boo::; # now it is only known as phoo::blonk:: + + # At this point, before the bug was fixed, %phoo::blonk::blonk:: ended + # up with no effective name, allowing it to be deleted without updating + # its subclasses’ caches. + + my $accum = ''; + + $accum .= 'feedlebomp'->phoo; # bbb + delete ${"phoo::blonk::"}{"blonk::"}; + $accum .= 'feedlebomp'->phoo; # bbb (Oops!) + @feedlebomp::ISA = @feedlebomp::ISA; + $accum .= 'feedlebomp'->phoo; # lasrevinu + + is $accum, 'bbblasrevinulasrevinu', + 'nested classes deleted & added simultaneously'; +} +use warnings; # mro_package_moved needs to check for self-referential packages. # This broke Text::Template [perl #78362]. |