Update isarev when clobbered class has subsubclasses
authorFather Chrysostomos <sprout@cpan.org>
Sat, 13 Nov 2010 00:34:02 +0000 (16:34 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 13 Nov 2010 00:34:28 +0000 (16:34 -0800)
commit90ba1f34dee5c0381e098e7c0435f354e2e70cf8
tree327d515f3969b762a7014a86fcb9dfff67a4cf97
parentfd0eba1997caf19767d67b8336533666df3fea90
Update isarev when clobbered class has subsubclasses

This fixes a case that mro_package_moved did not take into account:
If a class with multiple levels of subclasses was assigned over, then,
depending on the order in which the subclasses were processed in the
second loop in mro_package_moved, the subclasses might not be removed
from the isarev hashes of superclasses of the clobbered class.

This was because a call to mro_isa_changed_in on one class could call
mro_get_linear_isa on another class in the list, overwriting its
meta->isa hash, which is used to determine what to delete from
PL_isarev.

E.g., if D isa C isa B isa A, this assignment:

  *B:: = *something::;

would cause B, C and D to be iterated over, but not in any particular
order. The order could be D, C, B, in which case mro_isa_changed_in(D)
would overwrite the meta->isa hash in C with one that did not list A.
So mro_isa_changed_in(C) would not see A in meta->isa and would not
delete PL_isarev->{A}{C}.

This commit stores the meta->isa hash as the value in the ‘big list’,
instead of the stash. The stash itself can be retrieved from the key,
since it is already a memory address (a pointer cast to a char array).
The recorded isa hash in inserted into each stash before the call to
mro_isa_changed_in.
mro.c
t/mro/isarev.t