Make $class->method work when $class is tied
authorFather Chrysostomos <sprout@cpan.org>
Thu, 25 Aug 2011 01:04:26 +0000 (18:04 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 25 Aug 2011 01:04:26 +0000 (18:04 -0700)
commitda6b625f78f5f1335aee4b2f800c850ca4fbf7d9
tree0b8dc9b2d1b4516f23fdcde77c606614a9fa6c56
parent49b82a38ba415eac27865ed1f3a45e41896b4c66
Make $class->method work when $class is tied

This little script:

sub TIESCALAR{bless[]}
sub FETCH{warn "fetching"; "main"}
sub bolgy { warn 'bolgy' }
tie my $a, "";
$a->bolgy;

Gives these outputs with various versions of perl:

$ pbpaste|perl5.6.2
fetching at - line 2.
fetching at - line 2.
bolgy at - line 3.

$ pbpaste|perl5.8.8
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
Can't call method "bolgy" without a package or object reference at - line 5.

$ pbpaste|perl5.8.9
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
bolgy at - line 3.

$ pbpaste|perl5.10.0
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
Can't call method "bolgy" without a package or object reference at - line 5.

$ pbpaste|perl5.10.1 # also 5.12.x
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
bolgy at - line 3.

$ pbpaste|perl5.14.0
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
fetching at - line 2.
Can't locate object method "bolgy" via package "main" (perhaps you forgot to load "main"?) at - line 5.

It’s worse than ever in 5.14.

What’s happening is that S_method_common is hanging on to the pointer
returned by SvPV, while continuing to call get-magic again and again.
 So the pointer becomes invalid.  I think it’s only by accident that
it worked in some versions.

This commit stops S_method_common from calling get-magic so many
times, solving both problems.

I’m afraid this conflicts with ongoing work to make method lookup
UTF8-clean, but I wanted to make a patch that could be backported.
pp_hot.c
t/op/method.t
t/op/tie_fetch_count.t