Closed p5pRT closed 12 years ago
% perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1.
Use of uninitialized value $+{"X"} in string at -e line 1.
% perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+\, even if AUTOLOAD is never called. But (for some reason) letting the parser see %+ early makes things work as expected.
As far as I can tell this is broken in 5.12 and 5.10 but works in 5.14\, probably because Tie::Hash::NamedCapture is a real (XS) module there.
Any idea what's going on?
Additional data points ... This is what I got on Linux for first 5.12.0\, then 5.14.2:
###
$ /usr/local/bin/perl5.12.0 -wle '{ package UNIVERSAL; sub AUTOLOAD {
warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
###
$ perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" }
} "a" =~ /(?\
Similar results with these two Perl versions on Darwin.
The RT System itself - Status changed from 'new' to 'open'
On Wed Nov 30 13:39:47 2011\, l.mai@web.de wrote:
% perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1. Use of uninitialized value $+{"X"} in string at -e line 1. % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1. a Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8)) at -e line 1 during global destruction.
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global destruction.
So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+\, even if AUTOLOAD is never called. But (for some reason) letting the parser see %+ early makes things work as expected.
As far as I can tell this is broken in 5.12 and 5.10 but works in 5.14\, probably because Tie::Hash::NamedCapture is a real (XS) module there.
Any idea what's going on?
It was indeed this commit that made the difference\, but I cannot understand why:
commit 8dcfe2e99a72fe7951b4d15325e1541232823204 Author: Nicholas Clark \nick@​ccl4\.org Date: Thu Oct 14 15:34:03 2010 +0100
Move remaining Tie::Hash::NamedCapture XS code to NamedCapture.xs
Now all the support code for %+ and %- is contained in the module in
ext/
--
Father Chrysostomos
On Wed Nov 30 17:49:48 2011\, sprout wrote:
On Wed Nov 30 13:39:47 2011\, l.mai@web.de wrote:
% perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1. Use of uninitialized value $+{"X"} in string at -e line 1. % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1. a Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8))
at -e line 1 during global destruction.
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8))
at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global destruction.
So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+\, even if AUTOLOAD is never called. But (for some reason) letting the parser see %+ early makes things work as expected.
As far as I can tell this is broken in 5.12 and 5.10 but works in 5.14\, probably because Tie::Hash::NamedCapture is a real (XS) module there.
Any idea what's going on?
It was indeed this commit that made the difference\, but I cannot understand why:
commit 8dcfe2e99a72fe7951b4d15325e1541232823204 Author: Nicholas Clark \nick@​ccl4\.org Date: Thu Oct 14 15:34:03 2010 +0100
Move remaining Tie​::Hash​::NamedCapture XS code to NamedCapture\.xs Now all the support code for %\+ and %\- is contained in the module in
ext/
I’ve just figured it out. In gv.c:
S_require_tie_mod(pTHX_ GV *gv\, const char *varpv\, SV* namesv\, const char *methpv\,const U32 flags) { dVAR; HV* stash = gv_stashsv(namesv\, 0);
PERL_ARGS_ASSERT_REQUIRE_TIE_MOD;
if (!stash || !(gv_fetchmethod(stash\, methpv))) {
In gv.h:
#define gv_fetchmethod(stash\, name) gv_fetchmethod_autoload(stash\, name\, TRUE)
So\, if either the stash does not exist (as in 5.14; in 5.12 parts of it are in core)\, or the method (TIEHASH in this case) cannot be found\, even by autoloading\, then the module is loaded.
That means the problem still persists in 5.14. You just have to mention the package (e.g.\, ‘Tie::Hash::NamedCapture::Googoo() if 0’) and the presence of a universal autoload sub will stop (compilation of) %- and %+ from loading the module.
S_require_tie_mod probably should not be autoloading.
Errno and arybase have the same problem:
$ ./perl -Ilib -le 'arybase::Googoo() if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } $[ = 1; print qw(a b c)[2]' IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1. c
(should print b)
$ ./perl -Ilib -le 'Errno::onrrE() if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } $!=20; print $!{ENOTDIR}' IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1.
(should print 20\, on Unix at least)
--
Father Chrysostomos
On Wed Nov 30 18:04:50 2011\, sprout wrote:
On Wed Nov 30 17:49:48 2011\, sprout wrote:
On Wed Nov 30 13:39:47 2011\, l.mai@web.de wrote:
% perl -wle '{ package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x9447790)) at -e line 1. Use of uninitialized value $+{"X"} in string at -e line 1. % perl -wle '%- if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } "a" =~ /(?\
.)/ or die; print "$+{X}"' IO::File::DESTROY(IO::File=IO(0x823f798)) at -e line 1. a Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fba8))
at -e line 1 during global destruction.
Tie::Hash::NamedCapture::DESTROY(Tie::Hash::NamedCapture=SCALAR(0x823fca8))
at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f078)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f0f8)) at -e line 1 during global destruction. IO::File::DESTROY(IO::File=IO(0x823f178)) at -e line 1 during global destruction.
So apparently just creating UNIVERSAL::AUTOLOAD is enough to break %+\, even if AUTOLOAD is never called. But (for some reason) letting the parser see %+ early makes things work as expected.
As far as I can tell this is broken in 5.12 and 5.10 but works in 5.14\, probably because Tie::Hash::NamedCapture is a real (XS) module there.
Any idea what's going on?
It was indeed this commit that made the difference\, but I cannot understand why:
commit 8dcfe2e99a72fe7951b4d15325e1541232823204 Author: Nicholas Clark \nick@​ccl4\.org Date: Thu Oct 14 15:34:03 2010 +0100
Move remaining Tie​::Hash​::NamedCapture XS code to NamedCapture\.xs Now all the support code for %\+ and %\- is contained in the module in
ext/
I’ve just figured it out. In gv.c:
S_require_tie_mod(pTHX_ GV *gv\, const char *varpv\, SV* namesv\, const char *methpv\,const U32 flags) { dVAR; HV* stash = gv_stashsv(namesv\, 0);
PERL\_ARGS\_ASSERT\_REQUIRE\_TIE\_MOD; if \(\!stash || \!\(gv\_fetchmethod\(stash\, methpv\)\)\) \{
In gv.h:
#define gv_fetchmethod(stash\, name) gv_fetchmethod_autoload(stash\, name\, TRUE)
So\, if either the stash does not exist (as in 5.14; in 5.12 parts of it are in core)\, or the method (TIEHASH in this case) cannot be found\, even by autoloading\, then the module is loaded.
That means the problem still persists in 5.14. You just have to mention the package (e.g.\, ‘Tie::Hash::NamedCapture::Googoo() if 0’) and the presence of a universal autoload sub will stop (compilation of) %- and %+ from loading the module.
S_require_tie_mod probably should not be autoloading.
Errno and arybase have the same problem:
$ ./perl -Ilib -le 'arybase::Googoo() if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } $[ = 1; print qw(a b c)[2]' IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1. c
(should print b)
$ ./perl -Ilib -le 'Errno::onrrE() if 0; { package UNIVERSAL; sub AUTOLOAD { warn "$AUTOLOAD(@_)" } } $!=20; print $!{ENOTDIR}' IO::File::DESTROY(IO::File=IO(0x823220)) at -e line 1.
(should print 20\, on Unix at least)
Now fixed with commit 0ea03996e. I hope my responses have given you enough information to pick the workaround of your choice.
Now\, back to tending the COWs....
--
Father Chrysostomos
@cpansprout - Status changed from 'open' to 'resolved'
Migrated from rt.perl.org#105024 (status was 'resolved')
Searchable as RT105024$