diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-07-09 08:26:05 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-07-09 20:28:57 -0700 |
commit | a77c16f7c797af630db968764807f48bed555b91 (patch) | |
tree | 9266b36c6c74fec696cf9cb9725efb1b29c521a4 /t/op/method.t | |
parent | 6ea81ccfc852fdeb1f2b4a07ebfbb5ccf65f3239 (diff) | |
download | perl-a77c16f7c797af630db968764807f48bed555b91.tar.gz |
Make method lookup treat *foo as \*foo
It is possible to call a method on a typeglob with an IO thingy, as in
*ARGV->getline. This treats the invocant as a handle and looks up its
methods in IO::File.
As of commit 7156e69, a typeglob without an IO thingy is treated
as a class:
$ ./perl -Ilib -e 'sub foo::oof { print "foof!\n" } *foo->oof'
foof!
It did not occur to me back then that globs were being stringified in
method lookup.
Before that commit, names beginning with a non-alphabetic character
were permitted for handle names, but not for package names. That
fact, and the fact that symbol lookup in general will ignore an ini-
tial * followed by a letter, allowed *ARGV->getline to work.
For *Package->foo to work was a mistake.
It turns out, also, that the glob stringification could cause the
wrong handle to be used, e.g., after glob aliasing. Also, a handle
whose stringification begins with * followed by a non-alphabetic char-
acter will not work, because symbol lookup does not strip * from the
stringified glob:
$ ./perl -Ilib -e '$::Foo::VERSION; package Foo; open FH, "perl"; *FH->getline'
Can't locate object method "getline" via package "*::Foo::FH" (perhaps you forgot to load "*::Foo::FH"?) at -e line 1.
This commit fixes all this inconsistency by simply not stringifying
the glob. *FH->foo is now treated the same way as (\*FH)->foo (as it
already was in those cases where it worked).
This does allow PVLV globs to reach code that they couldn’t reach
before, so this patch has to handle those, too. (newRV probably ought
to handle PVLVs, but it currently doesn’t.)
Diffstat (limited to 't/op/method.t')
-rw-r--r-- | t/op/method.t | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/t/op/method.t b/t/op/method.t index 821f60468d..d206fc75fe 100644 --- a/t/op/method.t +++ b/t/op/method.t @@ -13,7 +13,7 @@ BEGIN { use strict; no warnings 'once'; -plan(tests => 142); +plan(tests => 146); @A::ISA = 'B'; @B::ISA = 'C'; @@ -490,6 +490,24 @@ is "3foo"->CORE::uc, '3FOO', '"3foo"->CORE::uc'; { no strict; @{"3foo::ISA"} = "CORE"; } is "3foo"->uc, '3FOO', '"3foo"->uc (autobox style!)'; +# *foo vs (\*foo) +sub myclass::squeak { 'eek' } +eval { *myclass->squeak }; +like $@, + qr/^Can't call method "squeak" without a package or object reference/, + 'method call on typeglob ignores package'; +eval { (\*myclass)->squeak }; +like $@, + qr/^Can't call method "squeak" on unblessed reference/, + 'method call on \*typeglob'; +*stdout2 = *STDOUT; # stdout2 now stringifies as *main::STDOUT +sub IO::Handle::self { $_[0] } +# This used to stringify the glob: +is *stdout2->self, (\*stdout2)->self, + '*glob->method is equiv to (\*glob)->method'; +sub { $_[0] = *STDOUT; is $_[0]->self, \$::h{k}, '$pvlv_glob->method' } + ->($::h{k}); + # Test that PL_stashcache doesn't change the resolution behaviour for file # handles and package names. SKIP: { |