Skip Menu |
Report information
Id: 47113
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: btilly [at] gmail.com
Cc:
AdminCc:

Operating System: Linux
PatchStatus: (no value)
Severity: low
Type: core
Perl Version: 5.8.6
Fixed In: (no value)



Subject: UNIVERSAL::can is wrong for unloaded classes
Date: Fri, 2 Nov 2007 11:02:39 -0700
To: perlbug [...] perl.org
From: Benjamin Tilly - Report Architect <btilly [...] pictage.com>
Download (untitled) / with headers
text/plain 5.6k
This is a bug report for perl from btilly@gmail.com, generated with the help of perlbug 1.35 running under perl v5.8.6. ----------------------------------------------------------------- [Please enter your report here] unless (Foo->can("can")) { print "can tells me that it can't be called!" } As the code snippet above demonstrates, if the package Foo is not yet in the symbol table, you can call the can method on it, but can will incorrectly not see that UNIVERSAL methods can be called on Foo. In case anyone wonders whether the ability to call can is a special case, I already tested that. sub UNIVERSAL::bar { print "bar was called\n"; } Foo->bar(); # Prints print Foo->can("bar"); # Doesn't find the method After the line "package Foo;" has been read, though, can will work correctly. This behaviour came up in http://use.perl.org/comments.pl?sid=37415. It leads to this incorrect warning from the core module UNIVERSAL::can: use warnings; use UNIVERSAL::can; # This warns that we're calling can as a function. # But we aren't! unless (Foo->can("new")) { print "Foo is not loaded\n"; } I've also submitted a patch to chromatic that would get rid of this incorrect warning. But his code was logically correct, and would not have warned were it not for the core Perl bug. Cheers, Ben [Please do not change anything below this line] ----------------------------------------------------------------- --- Flags: category=core severity=low --- This perlbug was built using Perl v5.8.6 in the Red Hat build system. It is being executed now by Perl v5.8.6 - Wed May 18 18:20:12 EDT 2005. Site configuration information for perl v5.8.6: Configured by Red Hat, Inc. at Wed May 18 18:20:12 EDT 2005. Summary of my perl5 (revision 5 version 8 subversion 6) configuration: Platform: osname=linux, osvers=2.4.21-27.0.2.elsmp, archname=i386-linux-thread-multi uname='linux decompose.build.redhat.com 2.4.21-27.0.2.elsmp #1 smp wed jan 12 23:35:44 est 2005 i686 i686 i386 gnulinux ' config_args='-des -Doptimize=-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -m32 -march=i386 -mtune=pentium4 -fasynchronous-unwind-tables -Dversion=5.8.6 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_endprotoent_r_proto -Ud_endservent_r_proto -Ud_sethostent_r_proto -Ud_setprotoent_r_proto -Ud_setservent_r_proto -Dinc_version_list=5.8.5 5.8.4 5.8.3' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemultiplicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', optimize='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -m32 -march=i386 -mtune=pentium4 -fasynchronous-unwind-tables', cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -I/usr/local/include -I/usr/include/gdbm' ccversion='', gccversion='4.0.0 20050516 (Red Hat 4.0.0-6)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='gcc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=/lib/libc-2.3.5.so, so=so, useshrplib=true, libperl=libperl.so gnulibc_version='2.3.5' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.6/i386-linux-thread-multi/CORE' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' Locally applied patches: --- @INC for perl v5.8.6: /usr/lib/perl5/site_perl/5.8.6/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.4/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.6 /usr/lib/perl5/site_perl/5.8.5 /usr/lib/perl5/site_perl/5.8.4 /usr/lib/perl5/site_perl/5.8.3 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.6/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.4/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.6 /usr/lib/perl5/vendor_perl/5.8.5 /usr/lib/perl5/vendor_perl/5.8.4 /usr/lib/perl5/vendor_perl/5.8.3 /usr/lib/perl5/vendor_perl /usr/lib/perl5/5.8.6/i386-linux-thread-multi /usr/lib/perl5/5.8.6 . --- Environment for perl v5.8.6: HOME=/users/btilly LANG=en_US.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games:/opt/ant/bin:/opt/tomcat/bin:/opt/java/bin:/users/btilly/bin:/opt/java/bin:/opt/java/bin:/opt/java/bin PERL_BADLANG (unset) SHELL=/bin/bash
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 378b
I've pushed a fix for this to the doy/universal branch. It's pretty straightforward, but some of the tests in t/op/universal.t were testing for this behavior explicitly (checking that can() was false before a package existed and true afterwards), so I'm not sure if this is reasonable to just change directly. I am in favor of making this change though, so any input is welcome.
RT-Send-CC: perl5-porters [...] perl.org, doy [...] tozt.net
Download (untitled) / with headers
text/plain 543b
On Fri Jun 22 12:14:55 2012, doy wrote: Show quoted text
> I've pushed a fix for this to the doy/universal branch. It's pretty > straightforward, but some of the tests in t/op/universal.t were testing > for this behavior explicitly (checking that can() was false before a > package existed and true afterwards), so I'm not sure if this is > reasonable to just change directly. I am in favor of making this change > though, so any input is welcome.
I think $class->can('can') is a fairly popular way to see whether a class is loaded. -- Father Chrysostomos
CC: perl5-porters [...] perl.org
Subject: Re: [perl #47113] UNIVERSAL::can is wrong for unloaded classes
Date: Fri, 22 Jun 2012 14:50:09 -0500
To: Father Chrysostomos via RT <perlbug-followup [...] perl.org>
From: Jesse Luehrs <doy [...] tozt.net>
On Fri, Jun 22, 2012 at 12:35:32PM -0700, Father Chrysostomos via RT wrote: Show quoted text
> On Fri Jun 22 12:14:55 2012, doy wrote:
> > I've pushed a fix for this to the doy/universal branch. It's pretty > > straightforward, but some of the tests in t/op/universal.t were testing > > for this behavior explicitly (checking that can() was false before a > > package existed and true afterwards), so I'm not sure if this is > > reasonable to just change directly. I am in favor of making this change > > though, so any input is welcome.
> > I think $class->can('can') is a fairly popular way to see whether a > class is loaded.
But (as mst pointed out on #p5p) it doesn't do that at all: $ perl -E'package Foo::Bar; say Foo->can("can")' CODE(0x1f4a220) (since namespaces nest). And having $foo->can("can") not die and yet not return anything really seems nonsensical. This feels analogous to the defined(@array) issue, to me - people may be using it, but it really doesn't do what they think it does, and using it in this way can cause a lot of subtle bugs. -doy
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.1k
On Fri Jun 22 12:50:38 2012, doy@tozt.net wrote: Show quoted text
> On Fri, Jun 22, 2012 at 12:35:32PM -0700, Father Chrysostomos via RT
wrote: Show quoted text
> > On Fri Jun 22 12:14:55 2012, doy wrote:
> > > I've pushed a fix for this to the doy/universal branch. It's pretty > > > straightforward, but some of the tests in t/op/universal.t were
testing Show quoted text
> > > for this behavior explicitly (checking that can() was false before a > > > package existed and true afterwards), so I'm not sure if this is > > > reasonable to just change directly. I am in favor of making this
change Show quoted text
> > > though, so any input is welcome.
> > > > I think $class->can('can') is a fairly popular way to see whether a > > class is loaded.
> > But (as mst pointed out on #p5p) it doesn't do that at all: > > $ perl -E'package Foo::Bar; say Foo->can("can")' > CODE(0x1f4a220) > > (since namespaces nest). And having $foo->can("can") not die and yet not > return anything really seems nonsensical. This feels analogous to the > defined(@array) issue, to me - people may be using it, but it really > doesn't do what they think it does, and using it in this way can cause a > lot of subtle bugs.
Fairy nuff. :-) -- Father Chrysostomos
Subject: Re: [perl #47113] UNIVERSAL::can is wrong for unloaded classes
Date: Fri, 22 Jun 2012 16:16:11 -0400
To: perl5-porters [...] perl.org
From: Ricardo Signes <perl.p5p [...] rjbs.manxome.org>
Download (untitled) / with headers
text/plain 226b
* Jesse Luehrs via RT <perlbug-comment@perl.org> [2012-06-22T15:14:56] Show quoted text
> I am in favor of making this change though, so any input is welcome.
It seems to bring ->can closer to reflecting reality, which sounds good. -- rjbs
Download signature.asc
application/pgp-signature 490b

Message body not shown because it is not plain text.

RT-Send-CC: perl5-porters [...] perl.org
Fixed by 68b4061.


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org