Skip Menu |

This queue is for tickets about the Function-Parameters CPAN distribution.

Report information
The Basics
Id: 120804
Status: resolved
Priority: 0/
Queue: Function-Parameters

People
Owner: MAUKE [...] cpan.org
Requestors: duff [...] pobox.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 2.000002
Fixed in: 2.000003



Subject: Method modifier bug?
#!/usr/bin/env perl use Modern::Perl; package A { use Moo; use Function::Parameters qw< :std :modifiers >; use Data::Dumper::Concise; method foo($h) { say Dumper($h); } } package B { use Moo; use Function::Parameters qw< :std :modifiers >; extends 'A'; before foo($q) { $q->{'goober'} = 42; } } my $x = B->new; $x->foo({ "foo" => "bar" }); __END__ $ ./foo Deep recursion on subroutine "B::foo" at (eval 12) line 6. Killed # I expected something like { foo => "bar", goober => 42 } $ perl -V Summary of my perl5 (revision 5 version 20 subversion 3) configuration: Platform: osname=linux, osvers=2.6.32-504.el6.x86_64, archname=x86_64-linux uname='linux hal 2.6.32-504.el6.x86_64 #1 smp wed oct 15 04:27:16 utc 2014 x86_64 x86_64 x86_64 gnulinux ' config_args='-d -Dprefix=/hostonly/hal/hal/perl' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion='', gccversion='4.4.7 20120313 (Red Hat 4.4.7-11)', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /usr/lib /lib/../lib64 /usr/lib/../lib64 /lib /lib64 /usr/lib64 /usr/local/lib64 libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc libc=libc-2.12.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.12' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector' Characteristics of this binary (from libperl): Compile-time options: HAS_TIMES PERLIO_LAYERS PERL_DONT_CREATE_GVSV PERL_HASH_FUNC_ONE_AT_A_TIME_HARD PERL_MALLOC_WRAP PERL_NEW_COPY_ON_WRITE PERL_PRESERVE_IVUV USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF Built under linux Compiled at Jun 13 2016 18:26:39 @INC: /hostonly/hal/hal/perl/lib/site_perl/5.20.3/x86_64-linux /hostonly/hal/hal/perl/lib/site_perl/5.20.3 /hostonly/hal/hal/perl/lib/5.20.3/x86_64-linux /hostonly/hal/hal/perl/lib/5.20.3 . $ perl -MFunction::Parameters -E 'say $Function::Parameters::VERSION' 2.000002
On Thu Mar 30 15:56:04 2017, duff wrote: Show quoted text
> #!/usr/bin/env perl > > use Modern::Perl; > > package A { > use Moo; > use Function::Parameters qw< :std :modifiers >; > use Data::Dumper::Concise; > > method foo($h) { > say Dumper($h); > } > > } > > > package B { > use Moo; > use Function::Parameters qw< :std :modifiers >; > > extends 'A'; > > before foo($q) { > $q->{'goober'} = 42; > } > > } > > > my $x = B->new; > $x->foo({ "foo" => "bar" }); > > __END__ > > > $ ./foo > Deep recursion on subroutine "B::foo" at (eval 12) line 6. > Killed
Confirmed. Thanks for the report! Preliminary analysis: This is caused by F:P effectively doing 'sub foo;' before parsing the body, which then makes B->can("foo") return a stub sub, which confuses Class::Method::Modifiers into wrapping foo with itself. Fix: Don't try to predeclare subs if we have a custom install_sub. It doesn't make sense for modifiers anyway. (Note: Calling your test package "B" gets really confusing if you then want to use the core module of the same name to inspect CVs.)
On Thu Mar 30 15:56:04 2017, duff wrote: Show quoted text
> # I expected something like > { > foo => "bar", > goober => 42 > }
I can fix the bug in F:P, but that changes the output to: The method 'foo' is not found in the inheritance hierarchy for class B at /.../Class/Method/Modifiers.pm line 42. Class::Method::Modifiers::install_modifier("B", "before", "foo") called at /.../Moo/_Utils.pm line 44 Moo::_Utils::_install_modifier("B", "before", "foo", CODE(0xb54a2fd0)) called at /.../Moo.pm line 83 Moo::before("foo", CODE(0xb54a2fd0)) called at try.pl line 25 That's because method modifiers take effect at compile time (just like sub/fun/method), i.e. before 'extends' runs and establishes inheritance. I'm tempted to just make 'runtime => 1' the default in all ':modifiers'.
On Thu Mar 30 20:54:29 2017, MAUKE wrote: Show quoted text
> On Thu Mar 30 15:56:04 2017, duff wrote:
> > # I expected something like > > { > > foo => "bar", > > goober => 42 > > }
> > I can fix the bug in F:P, but that changes the output to: > > The method 'foo' is not found in the inheritance hierarchy for class B > at /.../Class/Method/Modifiers.pm line 42. > Class::Method::Modifiers::install_modifier("B", "before", > "foo") called at /.../Moo/_Utils.pm line 44 > Moo::_Utils::_install_modifier("B", "before", "foo", > CODE(0xb54a2fd0)) called at /.../Moo.pm line 83 > Moo::before("foo", CODE(0xb54a2fd0)) called at try.pl line 25 > > That's because method modifiers take effect at compile time (just like > sub/fun/method), i.e. before 'extends' runs and establishes > inheritance.
Ah, indeed. You even documented it that way, but my addled brain must have glossed over that bit at the time. Show quoted text
> I'm tempted to just make 'runtime => 1' the default in all > ':modifiers'.
Not thinking through the implications, that sounds right to me. Especially given how I'd like to use them :-) -Scott