summaryrefslogtreecommitdiff
path: root/t/op/method.t
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-07-09 08:26:05 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-07-09 20:28:57 -0700
commita77c16f7c797af630db968764807f48bed555b91 (patch)
tree9266b36c6c74fec696cf9cb9725efb1b29c521a4 /t/op/method.t
parent6ea81ccfc852fdeb1f2b4a07ebfbb5ccf65f3239 (diff)
downloadperl-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.t20
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: {